diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ef85c5..c987e15 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,11 +18,36 @@ on: types: [published] # 手动发布 Release 时也自动构建并上传 bin workflow_dispatch: # 允许手动触发 +permissions: + contents: read + +concurrency: + group: firmware-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + env: IDF_VERSION: v5.5.2 TARGET: esp32s3 jobs: + web-tests: + name: WebUI regression tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + cache-dependency-path: tests/prompts/package-lock.json + - run: npm ci --prefix tests/prompts + - run: npm test --prefix tests/prompts + - run: python3 tests/release/test_release.py + - name: Install Chrome for actual-page regressions + working-directory: tests/prompts + run: npx playwright install --with-deps chrome + - run: npm run test:browser --prefix tests/prompts + build: name: Build ESP32-S3 Firmware runs-on: ubuntu-latest @@ -129,13 +154,16 @@ jobs: # 编译成功后自动创建或更新 Release:tag 推送、main 推送或手动发布 Release release: name: Create or Update Release - needs: build - if: github.event_name == 'release' || startsWith(github.ref, 'refs/tags/v') || (github.ref == 'refs/heads/main' && github.event_name == 'push') + needs: [build, web-tests] + if: github.repository == 'RMinte-AI/TianshanOS' && (github.event_name == 'release' || startsWith(github.ref, 'refs/tags/v') || (github.ref == 'refs/heads/main' && github.event_name == 'push')) runs-on: ubuntu-latest permissions: contents: write # 创建 Release 需要写权限 steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.sha }} - name: Download artifacts uses: actions/download-artifact@v4 with: @@ -156,6 +184,13 @@ jobs: echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "Release tag: $TAG" + - name: Validate Chinese release notes and build version + env: + RELEASE_TAG: ${{ steps.release_tag.outputs.tag }} + BUILD_VERSION: ${{ needs.build.outputs.version }} + run: | + python3 tools/check_release.py "$RELEASE_TAG" "$BUILD_VERSION" + - name: Check if release already exists (main branch) if: github.ref == 'refs/heads/main' id: check @@ -181,6 +216,8 @@ jobs: firmware/**/*.bin firmware/**/flasher_args.json fail_on_unmatched_files: true - generate_release_notes: true + target_commitish: ${{ github.sha }} + body_path: docs/releases/${{ steps.release_tag.outputs.tag }}.md + generate_release_notes: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 4cf8c8a..37986b2 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,6 @@ password*.txt # Documentation frontend_modification.md frontend_emoji_list.md + +# Local regression dependencies +tests/prompts/node_modules/ diff --git a/build/TianShanOS.bin b/build/TianShanOS.bin index 552f5da..86c142e 100644 Binary files a/build/TianShanOS.bin and b/build/TianShanOS.bin differ diff --git a/build/www.bin b/build/www.bin index f37185b..14be972 100644 Binary files a/build/www.bin and b/build/www.bin differ diff --git a/components/ch405labs_esp_libssh2/libssh2/src/mbedtls.c b/components/ch405labs_esp_libssh2/libssh2/src/mbedtls.c index b4383c9..2d826bd 100644 --- a/components/ch405labs_esp_libssh2/libssh2/src/mbedtls.c +++ b/components/ch405labs_esp_libssh2/libssh2/src/mbedtls.c @@ -43,7 +43,7 @@ #ifdef ESP_PLATFORM #include "esp_log.h" #define MBEDTLS_DEBUG_TAG "libssh2_mbedtls" -#define MBEDTLS_DEBUG(fmt, ...) ESP_LOGI(MBEDTLS_DEBUG_TAG, fmt, ##__VA_ARGS__) +#define MBEDTLS_DEBUG(fmt, ...) ESP_LOGD(MBEDTLS_DEBUG_TAG, fmt, ##__VA_ARGS__) #define MBEDTLS_ERROR(fmt, ...) ESP_LOGE(MBEDTLS_DEBUG_TAG, fmt, ##__VA_ARGS__) #else #define MBEDTLS_DEBUG(fmt, ...) diff --git a/components/ch405labs_esp_libssh2/libssh2/src/userauth.c b/components/ch405labs_esp_libssh2/libssh2/src/userauth.c index 6d747c7..65620ae 100644 --- a/components/ch405labs_esp_libssh2/libssh2/src/userauth.c +++ b/components/ch405labs_esp_libssh2/libssh2/src/userauth.c @@ -47,7 +47,7 @@ /* ESP-IDF logging for debugging */ #ifdef ESP_PLATFORM #include "esp_log.h" -#define USERAUTH_DEBUG(fmt, ...) ESP_LOGI("libssh2_userauth", fmt, ##__VA_ARGS__) +#define USERAUTH_DEBUG(fmt, ...) ESP_LOGD("libssh2_userauth", fmt, ##__VA_ARGS__) #define USERAUTH_ERROR(fmt, ...) ESP_LOGE("libssh2_userauth", fmt, ##__VA_ARGS__) #else #define USERAUTH_DEBUG(fmt, ...) diff --git a/components/ts_api/CMakeLists.txt b/components/ts_api/CMakeLists.txt index 4d5efc4..611d2e0 100644 --- a/components/ts_api/CMakeLists.txt +++ b/components/ts_api/CMakeLists.txt @@ -41,5 +41,5 @@ idf_component_register( INCLUDE_DIRS "include" EMBED_FILES ${TS_API_EMBED_FILES} REQUIRES ts_core ts_drivers ts_led ts_net json ts_storage ts_security ts_ota ts_automation ts_cert ts_webui ts_config_pack - PRIV_REQUIRES ts_hal esp_timer esp_app_format spi_flash bootloader_support esp_wifi app_update esp_https_ota esp_http_client espressif__esp_websocket_client + PRIV_REQUIRES ts_https ts_hal esp_timer esp_app_format spi_flash bootloader_support esp_wifi app_update esp_https_ota esp_http_client espressif__esp_websocket_client ) diff --git a/components/ts_api/src/ts_api_automation.c b/components/ts_api/src/ts_api_automation.c index 0d41bb5..48233df 100644 --- a/components/ts_api/src/ts_api_automation.c +++ b/components/ts_api/src/ts_api_automation.c @@ -1,3 +1,6 @@ +#include "ts_rule_codec.h" +#include "ts_ssh_service.h" +#include /** * @file ts_api_automation.c * @brief TianShanOS Automation Engine API @@ -129,7 +132,7 @@ static esp_err_t api_automation_start(const cJSON *params, ts_api_result_t *resu result->message = strdup("Automation engine started"); } else if (ret == ESP_ERR_INVALID_STATE) { result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Engine already running or not initialized"); + result->message = strdup("Engine is stopping, busy, or not initialized"); } else { result->code = TS_API_ERR_INTERNAL; result->message = strdup("Failed to start automation engine"); @@ -150,7 +153,9 @@ static esp_err_t api_automation_stop(const cJSON *params, ts_api_result_t *resul result->message = strdup("Automation engine stopped"); } else { result->code = TS_API_ERR_INTERNAL; - result->message = strdup("Failed to stop automation engine"); + result->message = strdup(ret == ESP_ERR_TIMEOUT + ? "Automation is stopping; retry after active operations finish" + : "Failed to stop automation engine"); } return ESP_OK; @@ -472,6 +477,10 @@ static esp_err_t api_automation_variables_set(const cJSON *params, ts_api_result static esp_err_t api_automation_rules_list(const cJSON *params, ts_api_result_t *result) { result->data = cJSON_CreateObject(); + bool loaded, recovery; + ts_rule_config_status(&loaded, &recovery); + cJSON_AddBoolToObject(result->data, "loaded", loaded); + cJSON_AddBoolToObject(result->data, "recovery_required", recovery); cJSON *rules_array = cJSON_AddArrayToObject(result->data, "rules"); // 遍历所有规则 @@ -480,12 +489,17 @@ static esp_err_t api_automation_rules_list(const cJSON *params, ts_api_result_t ts_auto_rule_t rule; if (ts_rule_get_by_index(i, &rule) != ESP_OK) continue; + ts_rule_resolve_presentation(&rule); cJSON *rule_obj = cJSON_CreateObject(); cJSON_AddStringToObject(rule_obj, "id", rule.id); cJSON_AddStringToObject(rule_obj, "name", rule.name); cJSON_AddStringToObject(rule_obj, "icon", rule.icon[0] ? rule.icon : "⚡"); cJSON_AddBoolToObject(rule_obj, "enabled", rule.enabled); cJSON_AddBoolToObject(rule_obj, "manual_trigger", rule.manual_trigger); + cJSON_AddBoolToObject(rule_obj, "show_on_dashboard", rule.show_on_dashboard); + cJSON_AddBoolToObject(rule_obj, "allow_manual_trigger", rule.allow_manual_trigger); + cJSON_AddBoolToObject(rule_obj, "reference_unresolved", rule.reference_unresolved); + cJSON_AddNumberToObject(rule_obj, "revision", rule.revision); cJSON_AddNumberToObject(rule_obj, "trigger_count", rule.trigger_count); cJSON_AddNumberToObject(rule_obj, "last_trigger_ms", (double)rule.last_trigger_ms); cJSON_AddNumberToObject(rule_obj, "cooldown_ms", rule.cooldown_ms); @@ -493,6 +507,7 @@ static esp_err_t api_automation_rules_list(const cJSON *params, ts_api_result_t cJSON_AddNumberToObject(rule_obj, "actions_count", rule.action_count); cJSON_AddItemToArray(rules_array, rule_obj); + ts_rule_release(&rule); } cJSON_AddNumberToObject(result->data, "count", count); @@ -503,62 +518,157 @@ static esp_err_t api_automation_rules_list(const cJSON *params, ts_api_result_t /** * @brief automation.rules.enable - Enable a rule */ -static esp_err_t api_automation_rules_enable(const cJSON *params, ts_api_result_t *result) -{ - cJSON *id_param = cJSON_GetObjectItem(params, "id"); - if (!id_param || !cJSON_IsString(id_param)) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Missing 'id' parameter"); +static void rule_commit_reply(ts_api_result_t *result, esp_err_t ret, + const ts_rule_commit_result_t *commit) { + result->code = ret == ESP_OK ? TS_API_OK : TS_API_ERR_INVALID_ARG; + result->message = strdup(commit->error_code ? commit->error_code : "invalid_configuration"); + result->data = cJSON_CreateObject(); + if (!result->data) + return; + if (commit->applied < 0) + cJSON_AddNullToObject(result->data, "applied"); + else + cJSON_AddBoolToObject(result->data, "applied", commit->applied); + if (commit->durable < 0) + cJSON_AddNullToObject(result->data, "durable"); + else + cJSON_AddBoolToObject(result->data, "durable", commit->durable); + if (commit->mirror_synced < 0) + cJSON_AddNullToObject(result->data, "mirror_synced"); + else + cJSON_AddBoolToObject(result->data, "mirror_synced", commit->mirror_synced); + cJSON_AddNumberToObject(result->data, "revision", commit->revision); + cJSON_AddStringToObject(result->data, "error_code", + commit->error_code ? commit->error_code : "invalid_configuration"); +} +static esp_err_t rule_mutate_locked(const cJSON *params, ts_api_result_t *result, int operation) { + const cJSON *id = cJSON_GetObjectItemCaseSensitive(params, "id"), + *revision = cJSON_GetObjectItemCaseSensitive(params, "expected_revision"); + if (!cJSON_IsString(id) || !ts_rule_id_valid(id->valuestring) || !cJSON_IsNumber(revision) || + !isfinite(revision->valuedouble) || revision->valuedouble < 0 || + revision->valuedouble > UINT32_MAX || + trunc(revision->valuedouble) != revision->valuedouble) { + ts_api_result_error(result, TS_API_ERR_INVALID_ARG, + "refresh_required: refresh the interface before saving"); return ESP_OK; } - - esp_err_t ret = ts_rule_enable(id_param->valuestring); - - if (ret == ESP_OK) { - result->code = TS_API_OK; - result->message = strdup("Rule enabled"); - } else if (ret == ESP_ERR_NOT_FOUND) { - result->code = TS_API_ERR_NOT_FOUND; - result->message = strdup("Rule not found"); - } else { - result->code = TS_API_ERR_INTERNAL; - result->message = strdup("Failed to enable rule"); + uint32_t expected = revision->valuedouble; + ts_rule_commit_result_t commit = {.error_code = "invalid_configuration"}; + if (operation == 3) { + esp_err_t e = ts_rule_commit(NULL, id->valuestring, expected, &commit); + rule_commit_reply(result, e, &commit); + return ESP_OK; } - + ts_auto_rule_t old = {0}; + esp_err_t found = ts_rule_acquire(id->valuestring, &old); + cJSON *merged = found == ESP_OK ? ts_rule_encode(&old) : cJSON_CreateObject(); + if (found == ESP_OK && old.revision != expected) { + ts_rule_release(&old); + cJSON_Delete(merged); + commit.error_code = "revision_conflict"; + rule_commit_reply(result, ESP_ERR_INVALID_STATE, &commit); + return ESP_OK; + } + ts_rule_release(&old); + if (!merged) { + ts_api_result_error(result, TS_API_ERR_INTERNAL, "no_memory"); + return ESP_OK; + } + const cJSON *field; + cJSON_ArrayForEach(field, params) { + if (!field->string || !strcmp(field->string, "expected_revision")) + continue; + cJSON *copy = cJSON_Duplicate(field, true); + if (!copy) { + cJSON_Delete(merged); + ts_api_result_error(result, TS_API_ERR_INTERNAL, "no_memory"); + return ESP_OK; + } + cJSON_DeleteItemFromObjectCaseSensitive(merged, field->string); + if (!cJSON_AddItemToObject(merged, field->string, copy)) { + cJSON_Delete(copy); + cJSON_Delete(merged); + ts_api_result_error(result, TS_API_ERR_INTERNAL, "no_memory"); + return ESP_OK; + } + } + if (operation == 1 || operation == 2) { + cJSON_DeleteItemFromObject(merged, "enabled"); + if (!cJSON_AddBoolToObject(merged, "enabled", operation == 1)) { + cJSON_Delete(merged); + return ESP_ERR_NO_MEM; + } + } + ts_auto_rule_t candidate = {0}; + esp_err_t e = ts_rule_decode(merged, &candidate); + cJSON_Delete(merged); + if (e == ESP_OK) + e = ts_rule_commit(&candidate, id->valuestring, expected, &commit); + else + commit.error_code = e == ESP_ERR_NO_MEM ? "no_memory" : "invalid_configuration"; + ts_rule_dispose(&candidate); + rule_commit_reply(result, e, &commit); return ESP_OK; } -/** - * @brief automation.rules.disable - Disable a rule - */ -static esp_err_t api_automation_rules_disable(const cJSON *params, ts_api_result_t *result) -{ - cJSON *id_param = cJSON_GetObjectItem(params, "id"); - if (!id_param || !cJSON_IsString(id_param)) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Missing 'id' parameter"); +static esp_err_t rule_mutate(const cJSON *params, ts_api_result_t *result, int operation) { + if (!ts_rule_edit_begin()) { + ts_api_result_error(result, TS_API_ERR_INTERNAL, "configuration_busy"); return ESP_OK; } + esp_err_t ret = rule_mutate_locked(params, result, operation); + ts_rule_edit_end(); + return ret; +} +static esp_err_t api_automation_rules_enable(const cJSON *params, ts_api_result_t *result) { + return rule_mutate(params, result, 1); +} - esp_err_t ret = ts_rule_disable(id_param->valuestring); - - if (ret == ESP_OK) { - result->code = TS_API_OK; - result->message = strdup("Rule disabled"); - } else if (ret == ESP_ERR_NOT_FOUND) { - result->code = TS_API_ERR_NOT_FOUND; - result->message = strdup("Rule not found"); - } else { - result->code = TS_API_ERR_INTERNAL; - result->message = strdup("Failed to disable rule"); - } - - return ESP_OK; +/** + * @brief automation.rules.disable - Disable a rule + */ +static esp_err_t api_automation_rules_disable(const cJSON *params, ts_api_result_t *result) { + return rule_mutate(params, result, 2); } /** * @brief automation.rules.trigger - Manually trigger a rule */ +static esp_err_t service_request(const cJSON *params, ts_api_result_t *result, bool stop) { + const cJSON *id = cJSON_GetObjectItemCaseSensitive(params, "command_id"); + if (!cJSON_IsString(id) || !id->valuestring[0]) { + ts_api_result_error(result, TS_API_ERR_INVALID_ARG, "command_id required"); + return ESP_ERR_INVALID_ARG; + } + ts_ssh_service_status_t state = {0}; + esp_err_t ret = stop ? ts_ssh_service_stop(id->valuestring, &state) + : (cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(params, "verify")) + ? ts_ssh_service_query(id->valuestring, &state) + : ts_ssh_service_cached(id->valuestring, &state)); + cJSON *data = cJSON_CreateObject(); + if (!data) + return ESP_ERR_NO_MEM; + cJSON_AddStringToObject(data, "state", state.state[0] ? state.state : "unknown"); + cJSON_AddStringToObject(data, "last_known", state.last_known); + cJSON_AddStringToObject(data, "source", state.source); + cJSON_AddNumberToObject(data, "confirmed_ms", state.confirmed_ms); + cJSON_AddNumberToObject(data, "generation", state.generation); + cJSON_AddBoolToObject(data, "busy", state.busy); + if (ret == ESP_OK) + ts_api_result_ok(result, data); + else { + ts_api_result_error(result, TS_API_ERR_INTERNAL, "service_state_unconfirmed"); + result->data = data; + } + return ret; +} +static esp_err_t api_service_status(const cJSON *params, ts_api_result_t *result) { + return service_request(params, result, false); +} +static esp_err_t api_service_stop(const cJSON *params, ts_api_result_t *result) { + return service_request(params, result, true); +} + static esp_err_t api_automation_rules_trigger(const cJSON *params, ts_api_result_t *result) { cJSON *id_param = cJSON_GetObjectItem(params, "id"); @@ -589,701 +699,44 @@ static esp_err_t api_automation_rules_trigger(const cJSON *params, ts_api_result /** * @brief Convert operator to string */ -static const char *operator_to_string(ts_auto_operator_t op) -{ - switch (op) { - case TS_AUTO_OP_EQ: return "eq"; - case TS_AUTO_OP_NE: return "ne"; - case TS_AUTO_OP_LT: return "lt"; - case TS_AUTO_OP_LE: return "le"; - case TS_AUTO_OP_GT: return "gt"; - case TS_AUTO_OP_GE: return "ge"; - case TS_AUTO_OP_CONTAINS: return "contains"; - case TS_AUTO_OP_CHANGED: return "changed"; - case TS_AUTO_OP_CHANGED_TO: return "changed_to"; - default: return "eq"; - } -} /** * @brief automation.rules.get - Get rule details by ID */ -static esp_err_t api_automation_rules_get(const cJSON *params, ts_api_result_t *result) -{ - cJSON *id_param = cJSON_GetObjectItem(params, "id"); - if (!id_param || !cJSON_IsString(id_param)) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Missing 'id' parameter"); - return ESP_OK; - } - - const ts_auto_rule_t *rule = ts_rule_get(id_param->valuestring); - if (!rule) { - result->code = TS_API_ERR_NOT_FOUND; - result->message = strdup("Rule not found"); +static esp_err_t api_automation_rules_get(const cJSON *params, ts_api_result_t *result) { + const cJSON *id = cJSON_GetObjectItemCaseSensitive(params, "id"); + ts_auto_rule_t rule; + if (!cJSON_IsString(id) || ts_rule_acquire(id->valuestring, &rule) != ESP_OK) { + ts_api_result_error(result, TS_API_ERR_NOT_FOUND, "Rule not found"); return ESP_OK; } - - result->data = cJSON_CreateObject(); - cJSON_AddStringToObject(result->data, "id", rule->id); - cJSON_AddStringToObject(result->data, "name", rule->name); - if (rule->icon[0]) { - cJSON_AddStringToObject(result->data, "icon", rule->icon); - } - cJSON_AddBoolToObject(result->data, "enabled", rule->enabled); - cJSON_AddBoolToObject(result->data, "manual_trigger", rule->manual_trigger); - cJSON_AddNumberToObject(result->data, "cooldown_ms", rule->cooldown_ms); - cJSON_AddStringToObject(result->data, "logic", - rule->conditions.logic == TS_AUTO_LOGIC_OR ? "or" : "and"); - cJSON_AddNumberToObject(result->data, "trigger_count", rule->trigger_count); - cJSON_AddNumberToObject(result->data, "last_trigger_ms", (double)rule->last_trigger_ms); - - // 添加条件数组 - cJSON *conditions = cJSON_AddArrayToObject(result->data, "conditions"); - for (int i = 0; i < rule->conditions.count; i++) { - const ts_auto_condition_t *c = &rule->conditions.conditions[i]; - cJSON *cond = cJSON_CreateObject(); - cJSON_AddStringToObject(cond, "variable", c->variable); - cJSON_AddStringToObject(cond, "operator", operator_to_string(c->op)); - - // 根据值类型添加值 - switch (c->value.type) { - case TS_AUTO_VAL_BOOL: - cJSON_AddBoolToObject(cond, "value", c->value.bool_val); - break; - case TS_AUTO_VAL_INT: - cJSON_AddNumberToObject(cond, "value", c->value.int_val); - break; - case TS_AUTO_VAL_FLOAT: - cJSON_AddNumberToObject(cond, "value", c->value.float_val); - break; - case TS_AUTO_VAL_STRING: - cJSON_AddStringToObject(cond, "value", c->value.str_val); - break; - default: - cJSON_AddNullToObject(cond, "value"); - break; - } - - cJSON_AddItemToArray(conditions, cond); - } - - // 获取所有动作模板用于匹配 - int tpl_count = ts_action_template_count(); - ts_action_template_t *templates = NULL; - if (tpl_count > 0) { - templates = heap_caps_malloc(sizeof(ts_action_template_t) * tpl_count, MALLOC_CAP_SPIRAM); - if (templates) { - size_t out_count = 0; - ts_action_template_list(templates, tpl_count, &out_count); - tpl_count = out_count; - } else { - tpl_count = 0; - } - } - - // 添加动作数组 - 完整序列化 - cJSON *actions = cJSON_AddArrayToObject(result->data, "actions"); - for (int i = 0; i < rule->action_count; i++) { - const ts_auto_action_t *a = &rule->actions[i]; - cJSON *act = cJSON_CreateObject(); - - // 添加动作类型 - const char *type_str = "log"; - switch (a->type) { - case TS_AUTO_ACT_LED: type_str = "led"; break; - case TS_AUTO_ACT_GPIO: type_str = "gpio"; break; - case TS_AUTO_ACT_DEVICE_CTRL: type_str = "device"; break; - case TS_AUTO_ACT_CLI: type_str = "cli"; break; - case TS_AUTO_ACT_LOG: type_str = "log"; break; - case TS_AUTO_ACT_SET_VAR: type_str = "set_var"; break; - case TS_AUTO_ACT_WEBHOOK: type_str = "webhook"; break; - case TS_AUTO_ACT_SSH_CMD: type_str = "ssh"; break; - case TS_AUTO_ACT_SSH_CMD_REF: type_str = "ssh_cmd_ref"; break; - default: type_str = "log"; break; - } - cJSON_AddStringToObject(act, "type", type_str); - cJSON_AddNumberToObject(act, "delay_ms", a->delay_ms); - - // 添加重复执行选项 - if (a->repeat_mode != TS_AUTO_REPEAT_ONCE) { - const char *repeat_mode_str = "once"; - switch (a->repeat_mode) { - case TS_AUTO_REPEAT_WHILE_TRUE: repeat_mode_str = "while_true"; break; - case TS_AUTO_REPEAT_COUNT: repeat_mode_str = "count"; break; - default: break; - } - cJSON_AddStringToObject(act, "repeat_mode", repeat_mode_str); - cJSON_AddNumberToObject(act, "repeat_interval_ms", a->repeat_interval_ms); - if (a->repeat_mode == TS_AUTO_REPEAT_COUNT) { - cJSON_AddNumberToObject(act, "repeat_count", a->repeat_count); - } - } - - // 如果有模板 ID,添加它 - if (a->template_id[0]) { - cJSON_AddStringToObject(act, "template_id", a->template_id); - } - - // 根据类型添加特定字段 - switch (a->type) { - case TS_AUTO_ACT_LED: - cJSON_AddStringToObject(act, "device", a->led.device); - cJSON_AddNumberToObject(act, "index", a->led.index); - cJSON_AddNumberToObject(act, "r", a->led.r); - cJSON_AddNumberToObject(act, "g", a->led.g); - cJSON_AddNumberToObject(act, "b", a->led.b); - if (a->led.effect[0]) { - cJSON_AddStringToObject(act, "effect", a->led.effect); - } - cJSON_AddNumberToObject(act, "duration_ms", a->led.duration_ms); - break; - case TS_AUTO_ACT_GPIO: - cJSON_AddNumberToObject(act, "pin", a->gpio.pin); - cJSON_AddBoolToObject(act, "level", a->gpio.level); - cJSON_AddNumberToObject(act, "pulse_ms", a->gpio.pulse_ms); - break; - case TS_AUTO_ACT_DEVICE_CTRL: - cJSON_AddStringToObject(act, "device", a->device.device); - cJSON_AddStringToObject(act, "action", a->device.action); - break; - case TS_AUTO_ACT_CLI: - cJSON_AddStringToObject(act, "command", a->cli.command); - break; - case TS_AUTO_ACT_LOG: - cJSON_AddStringToObject(act, "message", a->log.message); - cJSON_AddNumberToObject(act, "level", a->log.level); - break; - case TS_AUTO_ACT_SSH_CMD_REF: - cJSON_AddStringToObject(act, "cmd_id", a->ssh_ref.cmd_id); - break; - default: - break; - } - - // 尝试通过动作配置查找匹配的模板 ID(仅当没有保存 template_id 时) - if (!a->template_id[0]) { - for (int j = 0; j < tpl_count && templates; j++) { - ts_action_template_t *tpl = &templates[j]; - if (tpl->action.type == a->type) { - bool match = false; - switch (a->type) { - case TS_AUTO_ACT_CLI: - match = (strcmp(tpl->action.cli.command, a->cli.command) == 0); - break; - case TS_AUTO_ACT_LED: - match = (strcmp(tpl->action.led.device, a->led.device) == 0); - break; - case TS_AUTO_ACT_LOG: - match = (strcmp(tpl->action.log.message, a->log.message) == 0); - break; - default: - match = true; - break; - } - if (match) { - cJSON_AddStringToObject(act, "template_id", tpl->id); - break; - } - } - } - } - - // 序列化动作级别的条件 - if (a->condition.has_condition) { - cJSON *action_cond = cJSON_CreateObject(); - cJSON_AddStringToObject(action_cond, "variable", a->condition.variable); - cJSON_AddStringToObject(action_cond, "operator", operator_to_string(a->condition.op)); - - switch (a->condition.value.type) { - case TS_AUTO_VAL_BOOL: - cJSON_AddBoolToObject(action_cond, "value", a->condition.value.bool_val); - break; - case TS_AUTO_VAL_INT: - cJSON_AddNumberToObject(action_cond, "value", a->condition.value.int_val); - break; - case TS_AUTO_VAL_FLOAT: - cJSON_AddNumberToObject(action_cond, "value", a->condition.value.float_val); - break; - case TS_AUTO_VAL_STRING: - cJSON_AddStringToObject(action_cond, "value", a->condition.value.str_val); - break; - default: - cJSON_AddNullToObject(action_cond, "value"); - break; - } - - cJSON_AddItemToObject(act, "condition", action_cond); - } - - cJSON_AddItemToArray(actions, act); - } - - // 释放模板列表 - if (templates) { - free(templates); - } - - result->code = TS_API_OK; + ts_rule_resolve_presentation(&rule); + result->data = ts_rule_encode(&rule); + ts_rule_release(&rule); + result->code = result->data ? TS_API_OK : TS_API_ERR_INTERNAL; return ESP_OK; } /** * @brief Parse operator from string */ -static ts_auto_operator_t parse_operator(const char *op_str) -{ - if (!op_str) return TS_AUTO_OP_EQ; - if (strcmp(op_str, "eq") == 0 || strcmp(op_str, "==") == 0) return TS_AUTO_OP_EQ; - if (strcmp(op_str, "ne") == 0 || strcmp(op_str, "!=") == 0) return TS_AUTO_OP_NE; - if (strcmp(op_str, "lt") == 0 || strcmp(op_str, "<") == 0) return TS_AUTO_OP_LT; - if (strcmp(op_str, "le") == 0 || strcmp(op_str, "<=") == 0) return TS_AUTO_OP_LE; - if (strcmp(op_str, "gt") == 0 || strcmp(op_str, ">") == 0) return TS_AUTO_OP_GT; - if (strcmp(op_str, "ge") == 0 || strcmp(op_str, ">=") == 0) return TS_AUTO_OP_GE; - if (strcmp(op_str, "contains") == 0) return TS_AUTO_OP_CONTAINS; - if (strcmp(op_str, "changed") == 0) return TS_AUTO_OP_CHANGED; - if (strcmp(op_str, "changed_to") == 0) return TS_AUTO_OP_CHANGED_TO; - return TS_AUTO_OP_EQ; -} /** * @brief Parse action type from string */ -static ts_auto_action_type_t parse_action_type(const char *type_str) -{ - if (!type_str) return TS_AUTO_ACT_LOG; - if (strcmp(type_str, "led") == 0) return TS_AUTO_ACT_LED; - if (strcmp(type_str, "gpio") == 0) return TS_AUTO_ACT_GPIO; - if (strcmp(type_str, "ssh") == 0) return TS_AUTO_ACT_SSH_CMD; - if (strcmp(type_str, "ssh_cmd_ref") == 0) return TS_AUTO_ACT_SSH_CMD_REF; - if (strcmp(type_str, "webhook") == 0) return TS_AUTO_ACT_WEBHOOK; - if (strcmp(type_str, "log") == 0) return TS_AUTO_ACT_LOG; - if (strcmp(type_str, "set_var") == 0) return TS_AUTO_ACT_SET_VAR; - if (strcmp(type_str, "device") == 0) return TS_AUTO_ACT_DEVICE_CTRL; - return TS_AUTO_ACT_LOG; -} /** * @brief automation.rules.add - Add a new rule */ -static esp_err_t api_automation_rules_add(const cJSON *params, ts_api_result_t *result) -{ - // 必须参数 - cJSON *id_param = cJSON_GetObjectItem(params, "id"); - cJSON *name_param = cJSON_GetObjectItem(params, "name"); - - if (!id_param || !cJSON_IsString(id_param)) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Missing 'id' parameter"); - return ESP_OK; - } - - if (!name_param || !cJSON_IsString(name_param)) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Missing 'name' parameter"); - return ESP_OK; - } - - // 分配规则结构 - ts_auto_rule_t rule = {0}; - strncpy(rule.id, id_param->valuestring, sizeof(rule.id) - 1); - strncpy(rule.name, name_param->valuestring, sizeof(rule.name) - 1); - - // 图标(可选) - cJSON *icon = cJSON_GetObjectItem(params, "icon"); - if (icon && cJSON_IsString(icon)) { - strncpy(rule.icon, icon->valuestring, sizeof(rule.icon) - 1); - } else { - strncpy(rule.icon, "⚡", sizeof(rule.icon) - 1); - } - - // 可选参数 - cJSON *enabled = cJSON_GetObjectItem(params, "enabled"); - rule.enabled = enabled ? cJSON_IsTrue(enabled) : true; - - // 手动触发标记 - cJSON *manual_trigger = cJSON_GetObjectItem(params, "manual_trigger"); - rule.manual_trigger = manual_trigger ? cJSON_IsTrue(manual_trigger) : false; - - cJSON *cooldown = cJSON_GetObjectItem(params, "cooldown_ms"); - rule.cooldown_ms = cooldown && cJSON_IsNumber(cooldown) ? (uint32_t)cooldown->valueint : 0; - - // 解析条件数组 - cJSON *conditions = cJSON_GetObjectItem(params, "conditions"); - if (conditions && cJSON_IsArray(conditions)) { - int cond_count = cJSON_GetArraySize(conditions); - if (cond_count > 0) { - rule.conditions.conditions = heap_caps_calloc(cond_count, sizeof(ts_auto_condition_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rule.conditions.conditions) { - rule.conditions.count = cond_count; - - cJSON *logic_param = cJSON_GetObjectItem(params, "logic"); - if (logic_param && cJSON_IsString(logic_param) && strcmp(logic_param->valuestring, "or") == 0) { - rule.conditions.logic = TS_AUTO_LOGIC_OR; - } else { - rule.conditions.logic = TS_AUTO_LOGIC_AND; - } - - int idx = 0; - cJSON *cond; - cJSON_ArrayForEach(cond, conditions) { - ts_auto_condition_t *c = &rule.conditions.conditions[idx]; - - cJSON *var = cJSON_GetObjectItem(cond, "variable"); - cJSON *op = cJSON_GetObjectItem(cond, "operator"); - cJSON *val = cJSON_GetObjectItem(cond, "value"); - - if (var && cJSON_IsString(var)) { - strncpy(c->variable, var->valuestring, sizeof(c->variable) - 1); - } - if (op && cJSON_IsString(op)) { - c->op = parse_operator(op->valuestring); - } - if (val) { - if (cJSON_IsBool(val)) { - c->value.type = TS_AUTO_VAL_BOOL; - c->value.bool_val = cJSON_IsTrue(val); - } else if (cJSON_IsNumber(val)) { - c->value.type = TS_AUTO_VAL_FLOAT; - c->value.float_val = val->valuedouble; - } else if (cJSON_IsString(val)) { - c->value.type = TS_AUTO_VAL_STRING; - strncpy(c->value.str_val, val->valuestring, sizeof(c->value.str_val) - 1); - } - } - idx++; - } - } - } - } - - // 解析动作数组 - // 支持两种格式: - // 1. 模板引用: { "template_id": "xxx", "delay_ms": 0 } - // 2. 内联定义: { "type": "led", "device": "board", ... } (向后兼容) - cJSON *actions = cJSON_GetObjectItem(params, "actions"); - if (actions && cJSON_IsArray(actions)) { - int act_count = cJSON_GetArraySize(actions); - if (act_count > 0) { - rule.actions = heap_caps_calloc(act_count, sizeof(ts_auto_action_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rule.actions) { - rule.action_count = act_count; - - int idx = 0; - cJSON *act; - cJSON_ArrayForEach(act, actions) { - ts_auto_action_t *a = &rule.actions[idx]; - - // 检查是否是模板引用 - cJSON *template_id = cJSON_GetObjectItem(act, "template_id"); - if (template_id && cJSON_IsString(template_id)) { - // 从动作模板获取配置 - ts_action_template_t tpl; - if (ts_action_template_get(template_id->valuestring, &tpl) == ESP_OK) { - // 复制动作配置 - memcpy(a, &tpl.action, sizeof(ts_auto_action_t)); - - // 保存模板 ID 用于追踪 - strncpy(a->template_id, template_id->valuestring, sizeof(a->template_id) - 1); - - // 如果提供了覆盖的 delay_ms,使用它 - cJSON *delay = cJSON_GetObjectItem(act, "delay_ms"); - if (delay && cJSON_IsNumber(delay)) { - a->delay_ms = (uint16_t)delay->valueint; - } - - // 解析重复执行选项 - cJSON *repeat_mode = cJSON_GetObjectItem(act, "repeat_mode"); - if (repeat_mode && cJSON_IsString(repeat_mode)) { - if (strcmp(repeat_mode->valuestring, "while_true") == 0) { - a->repeat_mode = TS_AUTO_REPEAT_WHILE_TRUE; - } else if (strcmp(repeat_mode->valuestring, "count") == 0) { - a->repeat_mode = TS_AUTO_REPEAT_COUNT; - } else { - a->repeat_mode = TS_AUTO_REPEAT_ONCE; - } - } - - cJSON *repeat_count = cJSON_GetObjectItem(act, "repeat_count"); - if (repeat_count && cJSON_IsNumber(repeat_count)) { - a->repeat_count = (uint8_t)repeat_count->valueint; - } - - cJSON *repeat_interval = cJSON_GetObjectItem(act, "repeat_interval_ms"); - if (repeat_interval && cJSON_IsNumber(repeat_interval)) { - a->repeat_interval_ms = (uint16_t)repeat_interval->valueint; - } - - // 解析动作级别的条件 - cJSON *action_cond = cJSON_GetObjectItem(act, "condition"); - if (action_cond && cJSON_IsObject(action_cond)) { - a->condition.has_condition = true; - - cJSON *cond_var = cJSON_GetObjectItem(action_cond, "variable"); - cJSON *cond_op = cJSON_GetObjectItem(action_cond, "operator"); - cJSON *cond_val = cJSON_GetObjectItem(action_cond, "value"); - - if (cond_var && cJSON_IsString(cond_var)) { - strncpy(a->condition.variable, cond_var->valuestring, - sizeof(a->condition.variable) - 1); - } - if (cond_op && cJSON_IsString(cond_op)) { - a->condition.op = parse_operator(cond_op->valuestring); - } - if (cond_val) { - if (cJSON_IsBool(cond_val)) { - a->condition.value.type = TS_AUTO_VAL_BOOL; - a->condition.value.bool_val = cJSON_IsTrue(cond_val); - } else if (cJSON_IsNumber(cond_val)) { - a->condition.value.type = TS_AUTO_VAL_FLOAT; - a->condition.value.float_val = cond_val->valuedouble; - } else if (cJSON_IsString(cond_val)) { - a->condition.value.type = TS_AUTO_VAL_STRING; - strncpy(a->condition.value.str_val, cond_val->valuestring, - sizeof(a->condition.value.str_val) - 1); - } - } - - TS_LOGI(TAG, "Action condition: %s %d ...", - a->condition.variable, a->condition.op); - } - - TS_LOGI(TAG, "Rule action from template: %s (type=%d, repeat=%d)", - template_id->valuestring, a->type, a->repeat_mode); - } else { - TS_LOGW(TAG, "Action template not found: %s, using LOG action as placeholder", - template_id->valuestring); - // 设置为 LOG 类型,记录错误信息 - a->type = TS_AUTO_ACT_LOG; - a->log.level = 2; // ESP_LOG_WARN - snprintf(a->log.message, sizeof(a->log.message), - "Missing action template: %s", template_id->valuestring); - } - idx++; - continue; - } - - // 向后兼容:内联动作定义 - cJSON *type = cJSON_GetObjectItem(act, "type"); - if (type && cJSON_IsString(type)) { - a->type = parse_action_type(type->valuestring); - } - - cJSON *delay = cJSON_GetObjectItem(act, "delay_ms"); - a->delay_ms = delay && cJSON_IsNumber(delay) ? (uint16_t)delay->valueint : 0; - - // 根据类型解析参数 - switch (a->type) { - case TS_AUTO_ACT_LED: { - cJSON *device = cJSON_GetObjectItem(act, "device"); - cJSON *index = cJSON_GetObjectItem(act, "index"); - cJSON *r = cJSON_GetObjectItem(act, "r"); - cJSON *g = cJSON_GetObjectItem(act, "g"); - cJSON *b = cJSON_GetObjectItem(act, "b"); - cJSON *effect = cJSON_GetObjectItem(act, "effect"); - cJSON *duration = cJSON_GetObjectItem(act, "duration"); - - if (device && cJSON_IsString(device)) { - strncpy(a->led.device, device->valuestring, sizeof(a->led.device) - 1); - } - a->led.index = index && cJSON_IsNumber(index) ? (uint8_t)index->valueint : 0xFF; - a->led.r = r && cJSON_IsNumber(r) ? (uint8_t)r->valueint : 0; - a->led.g = g && cJSON_IsNumber(g) ? (uint8_t)g->valueint : 0; - a->led.b = b && cJSON_IsNumber(b) ? (uint8_t)b->valueint : 0; - if (effect && cJSON_IsString(effect)) { - strncpy(a->led.effect, effect->valuestring, sizeof(a->led.effect) - 1); - TS_LOGI(TAG, "Parsed LED action: device=%s, effect=%s", - a->led.device, a->led.effect); - } - a->led.duration_ms = duration && cJSON_IsNumber(duration) ? (uint16_t)duration->valueint : 0; - break; - } - case TS_AUTO_ACT_GPIO: { - cJSON *pin = cJSON_GetObjectItem(act, "pin"); - cJSON *level = cJSON_GetObjectItem(act, "level"); - cJSON *pulse = cJSON_GetObjectItem(act, "pulse_ms"); - - a->gpio.pin = pin && cJSON_IsNumber(pin) ? (uint8_t)pin->valueint : 0; - a->gpio.level = level && cJSON_IsTrue(level); - a->gpio.pulse_ms = pulse && cJSON_IsNumber(pulse) ? (uint32_t)pulse->valueint : 0; - break; - } - case TS_AUTO_ACT_DEVICE_CTRL: { - cJSON *device = cJSON_GetObjectItem(act, "device"); - cJSON *action = cJSON_GetObjectItem(act, "action"); - - if (device && cJSON_IsString(device)) { - strncpy(a->device.device, device->valuestring, sizeof(a->device.device) - 1); - } - if (action && cJSON_IsString(action)) { - strncpy(a->device.action, action->valuestring, sizeof(a->device.action) - 1); - } - break; - } - case TS_AUTO_ACT_LOG: { - cJSON *message = cJSON_GetObjectItem(act, "message"); - cJSON *level = cJSON_GetObjectItem(act, "level"); - - if (message && cJSON_IsString(message)) { - strncpy(a->log.message, message->valuestring, sizeof(a->log.message) - 1); - } - a->log.level = level && cJSON_IsNumber(level) ? (uint8_t)level->valueint : 3; // ESP_LOG_INFO - break; - } - case TS_AUTO_ACT_SET_VAR: { - cJSON *var = cJSON_GetObjectItem(act, "variable"); - cJSON *val = cJSON_GetObjectItem(act, "value"); - - if (var && cJSON_IsString(var)) { - strncpy(a->set_var.variable, var->valuestring, sizeof(a->set_var.variable) - 1); - } - if (val) { - if (cJSON_IsBool(val)) { - a->set_var.value.type = TS_AUTO_VAL_BOOL; - a->set_var.value.bool_val = cJSON_IsTrue(val); - } else if (cJSON_IsNumber(val)) { - a->set_var.value.type = TS_AUTO_VAL_FLOAT; - a->set_var.value.float_val = val->valuedouble; - } else if (cJSON_IsString(val)) { - a->set_var.value.type = TS_AUTO_VAL_STRING; - strncpy(a->set_var.value.str_val, val->valuestring, sizeof(a->set_var.value.str_val) - 1); - } - } - break; - } - case TS_AUTO_ACT_WEBHOOK: { - cJSON *url = cJSON_GetObjectItem(act, "url"); - cJSON *method = cJSON_GetObjectItem(act, "method"); - cJSON *body = cJSON_GetObjectItem(act, "body"); - - if (url && cJSON_IsString(url)) { - strncpy(a->webhook.url, url->valuestring, sizeof(a->webhook.url) - 1); - } - if (method && cJSON_IsString(method)) { - strncpy(a->webhook.method, method->valuestring, sizeof(a->webhook.method) - 1); - } else { - strcpy(a->webhook.method, "POST"); - } - if (body && cJSON_IsString(body)) { - strncpy(a->webhook.body_template, body->valuestring, sizeof(a->webhook.body_template) - 1); - } - break; - } - case TS_AUTO_ACT_SSH_CMD_REF: { - cJSON *cmd_id = cJSON_GetObjectItem(act, "cmd_id"); - if (cmd_id && cJSON_IsString(cmd_id)) { - strncpy(a->ssh_ref.cmd_id, cmd_id->valuestring, sizeof(a->ssh_ref.cmd_id) - 1); - TS_LOGI(TAG, "Parsed SSH_CMD_REF action: cmd_id=%s", a->ssh_ref.cmd_id); - } - break; - } - default: - break; - } - - // 解析内联动作的条件 - cJSON *action_cond = cJSON_GetObjectItem(act, "condition"); - if (action_cond && cJSON_IsObject(action_cond)) { - a->condition.has_condition = true; - - cJSON *cond_var = cJSON_GetObjectItem(action_cond, "variable"); - cJSON *cond_op = cJSON_GetObjectItem(action_cond, "operator"); - cJSON *cond_val = cJSON_GetObjectItem(action_cond, "value"); - - if (cond_var && cJSON_IsString(cond_var)) { - strncpy(a->condition.variable, cond_var->valuestring, - sizeof(a->condition.variable) - 1); - } - if (cond_op && cJSON_IsString(cond_op)) { - a->condition.op = parse_operator(cond_op->valuestring); - } - if (cond_val) { - if (cJSON_IsBool(cond_val)) { - a->condition.value.type = TS_AUTO_VAL_BOOL; - a->condition.value.bool_val = cJSON_IsTrue(cond_val); - } else if (cJSON_IsNumber(cond_val)) { - a->condition.value.type = TS_AUTO_VAL_FLOAT; - a->condition.value.float_val = cond_val->valuedouble; - } else if (cJSON_IsString(cond_val)) { - a->condition.value.type = TS_AUTO_VAL_STRING; - strncpy(a->condition.value.str_val, cond_val->valuestring, - sizeof(a->condition.value.str_val) - 1); - } - } - } - idx++; - } - } - } - } - - esp_err_t ret = ts_rule_register(&rule); - - // 释放分配的内存(ts_rule_register 会复制数据) - if (rule.conditions.conditions) { - free(rule.conditions.conditions); - } - if (rule.actions) { - free(rule.actions); - } - - if (ret == ESP_OK) { - result->code = TS_API_OK; - result->message = strdup("Rule created successfully"); - result->data = cJSON_CreateObject(); - cJSON_AddStringToObject(result->data, "id", rule.id); - } else if (ret == ESP_ERR_NO_MEM) { - result->code = TS_API_ERR_INTERNAL; - result->message = strdup("No memory for new rule"); - } else if (ret == ESP_ERR_INVALID_STATE) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Rule with this ID already exists"); - } else { - result->code = TS_API_ERR_INTERNAL; - result->message = strdup("Failed to create rule"); - } - - return ESP_OK; +static esp_err_t api_automation_rules_add(const cJSON *params, ts_api_result_t *result) { + return rule_mutate(params, result, 0); } /** * @brief automation.rules.delete - Delete a rule */ -static esp_err_t api_automation_rules_delete(const cJSON *params, ts_api_result_t *result) -{ - cJSON *id_param = cJSON_GetObjectItem(params, "id"); - if (!id_param || !cJSON_IsString(id_param)) { - result->code = TS_API_ERR_INVALID_ARG; - result->message = strdup("Missing 'id' parameter"); - return ESP_OK; - } - - const char *rule_id = id_param->valuestring; - esp_err_t ret = ts_rule_unregister(rule_id); - - if (ret == ESP_OK) { - // 同时删除 SD 卡上的配置文件(.json 和 .tscfg) - char filepath[128]; - snprintf(filepath, sizeof(filepath), "%s/%s.json", RULES_SDCARD_DIR, rule_id); - if (unlink(filepath) == 0) { - TS_LOGI(TAG, "Deleted rule config: %s", filepath); - } - snprintf(filepath, sizeof(filepath), "%s/%s.tscfg", RULES_SDCARD_DIR, rule_id); - if (unlink(filepath) == 0) { - TS_LOGI(TAG, "Deleted rule config pack: %s", filepath); - } - - result->code = TS_API_OK; - result->message = strdup("Rule deleted"); - } else if (ret == ESP_ERR_NOT_FOUND) { - result->code = TS_API_ERR_NOT_FOUND; - result->message = strdup("Rule not found"); - } else { - result->code = TS_API_ERR_INTERNAL; - result->message = strdup("Failed to delete rule"); - } - - return ESP_OK; +static esp_err_t api_automation_rules_delete(const cJSON *params, ts_api_result_t *result) { + return rule_mutate(params, result, 3); } /*===========================================================================*/ @@ -4184,7 +3637,7 @@ static esp_err_t api_automation_sources_export(const cJSON *params, ts_api_resul } // Copy to avoid holding lock memcpy(&source_copy, source, sizeof(ts_auto_source_t)); - + // Build export JSON cJSON *export_json = cJSON_CreateObject(); cJSON_AddStringToObject(export_json, "type", "automation_source"); @@ -4395,105 +3848,6 @@ static esp_err_t api_automation_sources_import(const cJSON *params, ts_api_resul /** * @brief Serialize rule to JSON for export */ -static cJSON *rule_to_export_json(const ts_auto_rule_t *rule) -{ - cJSON *obj = cJSON_CreateObject(); - cJSON_AddStringToObject(obj, "id", rule->id); - cJSON_AddStringToObject(obj, "name", rule->name); - if (rule->icon[0]) { - cJSON_AddStringToObject(obj, "icon", rule->icon); - } - cJSON_AddBoolToObject(obj, "enabled", rule->enabled); - cJSON_AddBoolToObject(obj, "manual_trigger", rule->manual_trigger); - cJSON_AddNumberToObject(obj, "cooldown_ms", rule->cooldown_ms); - cJSON_AddStringToObject(obj, "logic", - rule->conditions.logic == TS_AUTO_LOGIC_OR ? "or" : "and"); - - // Conditions - cJSON *conditions = cJSON_AddArrayToObject(obj, "conditions"); - for (int i = 0; i < rule->conditions.count; i++) { - const ts_auto_condition_t *c = &rule->conditions.conditions[i]; - cJSON *cond = cJSON_CreateObject(); - cJSON_AddStringToObject(cond, "variable", c->variable); - cJSON_AddStringToObject(cond, "operator", operator_to_string(c->op)); - switch (c->value.type) { - case TS_AUTO_VAL_BOOL: - cJSON_AddBoolToObject(cond, "value", c->value.bool_val); - break; - case TS_AUTO_VAL_INT: - cJSON_AddNumberToObject(cond, "value", c->value.int_val); - break; - case TS_AUTO_VAL_FLOAT: - cJSON_AddNumberToObject(cond, "value", c->value.float_val); - break; - case TS_AUTO_VAL_STRING: - cJSON_AddStringToObject(cond, "value", c->value.str_val); - break; - default: - cJSON_AddNullToObject(cond, "value"); - break; - } - cJSON_AddItemToArray(conditions, cond); - } - - // Actions - cJSON *actions = cJSON_AddArrayToObject(obj, "actions"); - for (int i = 0; i < rule->action_count; i++) { - const ts_auto_action_t *a = &rule->actions[i]; - cJSON *act = cJSON_CreateObject(); - - const char *type_str = "log"; - switch (a->type) { - case TS_AUTO_ACT_LED: type_str = "led"; break; - case TS_AUTO_ACT_GPIO: type_str = "gpio"; break; - case TS_AUTO_ACT_DEVICE_CTRL: type_str = "device"; break; - case TS_AUTO_ACT_CLI: type_str = "cli"; break; - case TS_AUTO_ACT_LOG: type_str = "log"; break; - case TS_AUTO_ACT_SET_VAR: type_str = "set_var"; break; - case TS_AUTO_ACT_WEBHOOK: type_str = "webhook"; break; - case TS_AUTO_ACT_SSH_CMD: type_str = "ssh"; break; - case TS_AUTO_ACT_SSH_CMD_REF: type_str = "ssh_cmd_ref"; break; - default: type_str = "log"; break; - } - cJSON_AddStringToObject(act, "type", type_str); - cJSON_AddNumberToObject(act, "delay_ms", a->delay_ms); - - if (a->template_id[0]) { - cJSON_AddStringToObject(act, "template_id", a->template_id); - } - - // Type-specific fields - switch (a->type) { - case TS_AUTO_ACT_LED: - cJSON_AddStringToObject(act, "device", a->led.device); - cJSON_AddNumberToObject(act, "index", a->led.index); - cJSON_AddNumberToObject(act, "r", a->led.r); - cJSON_AddNumberToObject(act, "g", a->led.g); - cJSON_AddNumberToObject(act, "b", a->led.b); - if (a->led.effect[0]) { - cJSON_AddStringToObject(act, "effect", a->led.effect); - } - cJSON_AddNumberToObject(act, "duration_ms", a->led.duration_ms); - break; - case TS_AUTO_ACT_CLI: - cJSON_AddStringToObject(act, "command", a->cli.command); - break; - case TS_AUTO_ACT_LOG: - cJSON_AddStringToObject(act, "message", a->log.message); - cJSON_AddNumberToObject(act, "level", a->log.level); - break; - case TS_AUTO_ACT_SSH_CMD_REF: - cJSON_AddStringToObject(act, "cmd_id", a->ssh_ref.cmd_id); - break; - default: - break; - } - - cJSON_AddItemToArray(actions, act); - } - - return obj; -} /** * @brief automation.rules.export - Export rule as config pack @@ -4516,18 +3870,27 @@ static esp_err_t api_automation_rules_export(const cJSON *params, ts_api_result_ "This device is not authorized to export config packs"); return ESP_OK; } - - const ts_auto_rule_t *rule = ts_rule_get(id->valuestring); - if (!rule) { + + ts_auto_rule_t snapshot; + if (ts_rule_acquire(id->valuestring, &snapshot) != ESP_OK) { ts_api_result_error(result, TS_API_ERR_NOT_FOUND, "Rule not found"); return ESP_OK; } - + + char rule_id[TS_AUTO_NAME_MAX_LEN]; + strcpy(rule_id, snapshot.id); // Build export JSON cJSON *export_json = cJSON_CreateObject(); cJSON_AddStringToObject(export_json, "type", "automation_rule"); - cJSON_AddItemToObject(export_json, "rule", rule_to_export_json(rule)); - + cJSON *encoded = ts_rule_encode(&snapshot); + ts_rule_release(&snapshot); + if (!encoded || !export_json || !cJSON_AddItemToObject(export_json, "rule", encoded)) { + cJSON_Delete(encoded); + cJSON_Delete(export_json); + ts_api_result_error(result, TS_API_ERR_INTERNAL, "no_memory"); + return ESP_OK; + } + char *json_str = cJSON_PrintUnformatted(export_json); cJSON_Delete(export_json); if (!json_str) { @@ -4571,9 +3934,9 @@ static esp_err_t api_automation_rules_export(const cJSON *params, ts_api_result_ char *tscfg_output = NULL; size_t tscfg_len = 0; - ts_config_pack_result_t pack_result = ts_config_pack_create( - rule->id, json_str, strlen(json_str), &opts, &tscfg_output, &tscfg_len); - + ts_config_pack_result_t pack_result = ts_config_pack_create(rule_id, json_str, strlen(json_str), + &opts, &tscfg_output, &tscfg_len); + cJSON_free(json_str); if (free_cert) free(cert_pem); @@ -4586,7 +3949,7 @@ static esp_err_t api_automation_rules_export(const cJSON *params, ts_api_result_ cJSON *data = cJSON_CreateObject(); cJSON_AddStringToObject(data, "tscfg", tscfg_output); char filename[80]; - snprintf(filename, sizeof(filename), "rule_%s.tscfg", rule->id); + snprintf(filename, sizeof(filename), "rule_%s.tscfg", rule_id); cJSON_AddStringToObject(data, "filename", filename); free(tscfg_output); @@ -4683,45 +4046,9 @@ static esp_err_t api_automation_rules_import(const cJSON *params, ts_api_result_ ts_api_result_ok(result, data); return ESP_OK; } - - // Ensure directory exists - if (stat(RULES_SDCARD_DIR, &st) != 0) { - mkdir(RULES_SDCARD_DIR, 0755); - } - - // Save .tscfg file - snprintf(filepath, sizeof(filepath), "%s/%s.tscfg", RULES_SDCARD_DIR, config_id); - FILE *f = fopen(filepath, "w"); - if (!f) { - ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to create config file"); - return ESP_OK; - } - - size_t written = fwrite(tscfg->valuestring, 1, strlen(tscfg->valuestring), f); - fclose(f); - - if (written != strlen(tscfg->valuestring)) { - unlink(filepath); - ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to write config file"); - return ESP_OK; - } - - // Delete old .json if overwriting - if (do_overwrite) { - char json_path[128]; - snprintf(json_path, sizeof(json_path), "%s/%s.json", RULES_SDCARD_DIR, config_id); - unlink(json_path); - } - - TS_LOGI(TAG, "Rule config imported: %s (will be loaded on restart)", filepath); - - cJSON *data = cJSON_CreateObject(); - cJSON_AddStringToObject(data, "id", config_id); - cJSON_AddStringToObject(data, "path", filepath); - cJSON_AddBoolToObject(data, "imported", true); - cJSON_AddBoolToObject(data, "overwritten", exists && do_overwrite); - cJSON_AddStringToObject(data, "note", "Restart system to load the new config"); - ts_api_result_ok(result, data); + + ts_api_result_error(result, TS_API_ERR_INVALID_ARG, + "source_read_only: encrypted rule import requires a recoverable writer"); return ESP_OK; } @@ -5151,6 +4478,16 @@ esp_err_t ts_api_automation_register(void) }; ts_api_register(&ep_rules_get); + ts_api_endpoint_t ep_service = {.name = "automation.services.status", + .description = "Confirm managed remote process state", + .category = TS_API_CAT_SYSTEM, + .handler = api_service_status, + .requires_auth = true}; + ts_api_register(&ep_service); + ep_service.name = "automation.services.stop"; + ep_service.handler = api_service_stop; + ep_service.description = "Stop verified managed remote process"; + ts_api_register(&ep_service); ts_api_endpoint_t ep_rules_trigger = { .name = "automation.rules.trigger", .description = "Manually trigger a rule", @@ -5168,6 +4505,10 @@ esp_err_t ts_api_automation_register(void) .requires_auth = true, }; ts_api_register(&ep_rules_add); + ts_api_endpoint_t ep_rules_update = ep_rules_add; + ep_rules_update.name = "automation.rules.update"; + ep_rules_update.description = "Update rule with expected revision"; + ts_api_register(&ep_rules_update); ts_api_endpoint_t ep_rules_delete = { .name = "automation.rules.delete", diff --git a/components/ts_api/src/ts_api_cert.c b/components/ts_api/src/ts_api_cert.c index 8c20cde..d1e02b0 100644 --- a/components/ts_api/src/ts_api_cert.c +++ b/components/ts_api/src/ts_api_cert.c @@ -17,6 +17,7 @@ #include "ts_api.h" #include "ts_cert.h" +#include "ts_https.h" #include "ts_log.h" #include #include @@ -41,9 +42,11 @@ static const char *status_to_display(ts_cert_status_t status) case TS_CERT_STATUS_CSR_PENDING: return "CSR 已生成,等待签发"; case TS_CERT_STATUS_ACTIVATED: - return "已激活"; + return "设备证书时间有效"; case TS_CERT_STATUS_EXPIRED: return "已过期"; + case TS_CERT_STATUS_TIME_UNVERIFIED: return "待校时确认"; + case TS_CERT_STATUS_NOT_YET_VALID: return "尚未生效"; case TS_CERT_STATUS_ERROR: return "错误"; default: @@ -51,6 +54,66 @@ static const char *status_to_display(ts_cert_status_t status) } } +static void add_validity(cJSON *data, const ts_cert_info_t *info) +{ + cJSON_AddStringToObject(data, "validity", ts_cert_validity_to_str(info->validity)); + cJSON_AddBoolToObject(data, "time_ready", info->time_ready); + cJSON_AddBoolToObject(data, "serial_truncated", info->serial_truncated); + if (info->time_ready && info->validity != TS_CERT_VALIDITY_INVALID && info->validity != TS_CERT_VALIDITY_NONE) + cJSON_AddNumberToObject(data, "seconds_until_expiry", (double)info->seconds_until_expiry); + else cJSON_AddNullToObject(data, "seconds_until_expiry"); + cJSON_AddBoolToObject(data, "expires_soon", info->is_valid && info->seconds_until_expiry < 30LL * 86400); +} + +static void add_runtime(cJSON *data, const ts_cert_pki_status_t *s) +{ + ts_https_runtime_t runtime; + ts_https_get_runtime(&runtime); + cJSON_AddBoolToObject(data, "time_ready", s->time_ready); + cJSON_AddStringToObject(data, "validity", ts_cert_validity_to_str(s->cert_info.validity)); + cJSON_AddNumberToObject(data, "configured_generation", s->generation); + cJSON_AddBoolToObject(data, "prerequisites_satisfied", ts_cert_prerequisites(s, runtime.require_client_cert)); + cJSON_AddBoolToObject(data, "restart_required", runtime.running && runtime.loaded_generation != s->generation); + cJSON *blocked = cJSON_AddArrayToObject(data, "blocked_by"); +#define BLOCK(condition, name) if (condition) cJSON_AddItemToArray(blocked, cJSON_CreateString(name)) + BLOCK(!s->time_ready, "time_not_ready"); + BLOCK(!s->has_private_key, "private_key_missing"); + BLOCK(s->has_private_key && !s->key_valid, "private_key_invalid"); + BLOCK(!s->has_certificate, "certificate_missing"); + BLOCK(s->has_certificate && s->cert_info.validity == TS_CERT_VALIDITY_INVALID, "certificate_invalid"); + BLOCK(s->has_certificate && s->key_valid && s->cert_info.validity != TS_CERT_VALIDITY_INVALID && !s->key_matches, "key_mismatch"); + BLOCK(s->cert_info.validity == TS_CERT_VALIDITY_NOT_YET_VALID, "not_yet_valid"); + BLOCK(s->cert_info.validity == TS_CERT_VALIDITY_EXPIRED, "expired"); + BLOCK(runtime.require_client_cert && !s->has_ca_chain, "ca_missing"); + BLOCK(runtime.require_client_cert && s->has_ca_chain && !s->ca_valid, "ca_invalid"); + BLOCK(s->storage_error, "storage_error"); +#undef BLOCK + cJSON *https = cJSON_AddObjectToObject(data, "https"); + cJSON_AddBoolToObject(https, "running", runtime.running); + cJSON_AddNumberToObject(https, "port", runtime.port); + if (runtime.running) { + cJSON_AddNumberToObject(https, "loaded_generation", runtime.loaded_generation); + cJSON_AddStringToObject(https, "loaded_certificate_sha256", runtime.loaded_certificate_sha256); + } else { + cJSON_AddNullToObject(https, "loaded_generation"); + cJSON_AddNullToObject(https, "loaded_certificate_sha256"); + } + if (runtime.last_error != ESP_OK) { + cJSON_AddStringToObject(https, "last_error_stage", runtime.last_error_stage); + cJSON_AddStringToObject(https, "last_error", esp_err_to_name(runtime.last_error)); + } else { + cJSON_AddNullToObject(https, "last_error_stage"); cJSON_AddNullToObject(https, "last_error"); + } +} + +static esp_err_t install_error(ts_api_result_t *result, esp_err_t err, ts_cert_op_error_t detail) +{ + ts_api_result_error(result, err == ESP_ERR_NO_MEM ? TS_API_ERR_NO_MEM : + err == ESP_ERR_INVALID_ARG ? TS_API_ERR_INVALID_ARG : TS_API_ERR_INTERNAL, + ts_cert_op_error_to_str(detail)); + return err; +} + /*===========================================================================*/ /* API Handlers */ /*===========================================================================*/ @@ -104,6 +167,8 @@ static esp_err_t api_cert_status(const cJSON *params, ts_api_result_t *result) cJSON_AddBoolToObject(data, "has_certificate", pki_status.has_certificate); cJSON_AddBoolToObject(data, "has_ca_chain", pki_status.has_ca_chain); + add_runtime(data, &pki_status); + // 如果有证书,添加证书信息 if (pki_status.has_certificate) { cJSON *cert_info = cJSON_CreateObject(); @@ -115,11 +180,8 @@ static esp_err_t api_cert_status(const cJSON *params, ts_api_result_t *result) cJSON_AddBoolToObject(cert_info, "is_valid", pki_status.cert_info.is_valid); cJSON_AddNumberToObject(cert_info, "days_until_expiry", pki_status.cert_info.days_until_expiry); - // 计算是否即将过期(30 天内) - cJSON_AddBoolToObject(cert_info, "expires_soon", - pki_status.cert_info.days_until_expiry >= 0 && - pki_status.cert_info.days_until_expiry < 30); - + add_validity(cert_info, &pki_status.cert_info); + cJSON_AddItemToObject(data, "cert_info", cert_info); } @@ -266,23 +328,12 @@ static esp_err_t api_cert_install(const cJSON *params, ts_api_result_t *result) } const char *cert_pem = cert_obj->valuestring; - size_t cert_len = strlen(cert_pem); - - esp_err_t ret = ts_cert_install_certificate(cert_pem, cert_len); - if (ret != ESP_OK) { - TS_LOGE(TAG, "Failed to install certificate: %s", esp_err_to_name(ret)); - - const char *err_msg = "Failed to install certificate"; - if (ret == ESP_ERR_INVALID_ARG) { - err_msg = "Invalid certificate format"; - } else if (ret == ESP_ERR_INVALID_STATE) { - err_msg = "Certificate does not match private key"; - } - - ts_api_result_error(result, TS_API_ERR_INTERNAL, err_msg); - return ret; - } + size_t cert_len = strlen(cert_pem) + 1; + ts_cert_op_error_t detail; + esp_err_t ret = ts_cert_install_certificate_ex(cert_pem, cert_len, &detail); + if (ret != ESP_OK) return install_error(result, ret, detail); + // 获取安装后的证书信息 ts_cert_info_t info; cJSON *data = cJSON_CreateObject(); @@ -296,6 +347,7 @@ static esp_err_t api_cert_install(const cJSON *params, ts_api_result_t *result) cJSON_AddNumberToObject(cert_info, "not_before", (double)info.not_before); cJSON_AddNumberToObject(cert_info, "not_after", (double)info.not_after); cJSON_AddNumberToObject(cert_info, "days_until_expiry", info.days_until_expiry); + add_validity(cert_info, &info); cJSON_AddItemToObject(data, "cert_info", cert_info); } @@ -323,16 +375,12 @@ static esp_err_t api_cert_install_ca(const cJSON *params, ts_api_result_t *resul } const char *ca_pem = ca_obj->valuestring; - size_t ca_len = strlen(ca_pem); - - esp_err_t ret = ts_cert_install_ca_chain(ca_pem, ca_len); - if (ret != ESP_OK) { - TS_LOGE(TAG, "Failed to install CA chain: %s", esp_err_to_name(ret)); - ts_api_result_error(result, TS_API_ERR_INTERNAL, - "Failed to install CA certificate chain"); - return ret; - } + size_t ca_len = strlen(ca_pem) + 1; + ts_cert_op_error_t detail; + esp_err_t ret = ts_cert_install_ca_chain_ex(ca_pem, ca_len, &detail); + if (ret != ESP_OK) return install_error(result, ret, detail); + cJSON *data = cJSON_CreateObject(); cJSON_AddBoolToObject(data, "success", true); cJSON_AddStringToObject(data, "message", "CA chain installed successfully"); diff --git a/components/ts_api/src/ts_api_ssh.c b/components/ts_api/src/ts_api_ssh.c index 62b562f..5d6ef53 100644 --- a/components/ts_api/src/ts_api_ssh.c +++ b/components/ts_api/src/ts_api_ssh.c @@ -45,35 +45,27 @@ #define TS_API_ERR_HOST_MISMATCH 1001 /* 主机指纹不匹配 */ #define TS_API_ERR_HOST_NEW 1002 /* 新主机需要确认 */ -/* 静态缓冲区用于存储主机、用户名等 */ -static char s_host_buf[64]; -static char s_user_buf[64]; -static char s_pass_buf[128]; -static char *s_key_buf = NULL; -static size_t s_key_len = 0; - -/*===========================================================================*/ -/* Helper Functions */ -/*===========================================================================*/ - -/** - * @brief 清理密钥缓冲区 - */ -static void cleanup_key_buffer(void) -{ - if (s_key_buf) { - memset(s_key_buf, 0, s_key_len); - free(s_key_buf); - s_key_buf = NULL; - s_key_len = 0; +/* Request-local key lifetime; concurrent callers must never share credentials. */ +typedef struct { + char *data; + size_t len; +} ssh_request_key_t; +static void cleanup_key_buffer(ssh_request_key_t *key) { + if (key->data) { + volatile unsigned char *p = (volatile unsigned char *)key->data; + for (size_t i = 0; i < key->len; ++i) + p[i] = 0; + free(key->data); + key->data = NULL; + key->len = 0; } } /** * @brief 从参数中配置 SSH 会话 */ -static esp_err_t configure_ssh_from_params(const cJSON *params, ts_ssh_config_t *config) -{ +static esp_err_t configure_ssh_from_params(const cJSON *params, ts_ssh_config_t *config, + ssh_request_key_t *request_key) { /* 主机和用户名 */ const cJSON *host = cJSON_GetObjectItem(params, "host"); const cJSON *user = cJSON_GetObjectItem(params, "user"); @@ -82,39 +74,32 @@ static esp_err_t configure_ssh_from_params(const cJSON *params, ts_ssh_config_t if (!host || !cJSON_IsString(host) || !user || !cJSON_IsString(user)) { return ESP_ERR_INVALID_ARG; } - - /* 复制到静态缓冲区 */ - strncpy(s_host_buf, host->valuestring, sizeof(s_host_buf) - 1); - s_host_buf[sizeof(s_host_buf) - 1] = '\0'; - strncpy(s_user_buf, user->valuestring, sizeof(s_user_buf) - 1); - s_user_buf[sizeof(s_user_buf) - 1] = '\0'; - - config->host = s_host_buf; - config->username = s_user_buf; + + config->host = host->valuestring; + config->username = user->valuestring; config->port = cJSON_IsNumber(port) ? port->valueint : 22; /* 认证方式:密码或密钥 */ const cJSON *password = cJSON_GetObjectItem(params, "password"); const cJSON *keyid = cJSON_GetObjectItem(params, "keyid"); const cJSON *keypath = cJSON_GetObjectItem(params, "keypath"); - - cleanup_key_buffer(); - + + cleanup_key_buffer(request_key); + if (cJSON_IsString(password) && password->valuestring[0]) { - strncpy(s_pass_buf, password->valuestring, sizeof(s_pass_buf) - 1); - s_pass_buf[sizeof(s_pass_buf) - 1] = '\0'; config->auth_method = TS_SSH_AUTH_PASSWORD; - config->auth.password = s_pass_buf; + config->auth.password = password->valuestring; } else if (cJSON_IsString(keyid) && keyid->valuestring[0]) { /* 从密钥存储读取私钥 */ - esp_err_t ret = ts_keystore_load_private_key(keyid->valuestring, &s_key_buf, &s_key_len); + esp_err_t ret = + ts_keystore_load_private_key(keyid->valuestring, &request_key->data, &request_key->len); if (ret != ESP_OK) { TS_LOGE(TAG, "Failed to load key '%s': %s", keyid->valuestring, esp_err_to_name(ret)); return ret; } config->auth_method = TS_SSH_AUTH_PUBLICKEY; - config->auth.key.private_key = (const uint8_t *)s_key_buf; - config->auth.key.private_key_len = s_key_len; + config->auth.key.private_key = (const uint8_t *)request_key->data; + config->auth.key.private_key_len = request_key->len; config->auth.key.private_key_path = NULL; config->auth.key.passphrase = NULL; } else if (cJSON_IsString(keypath) && keypath->valuestring[0]) { @@ -153,8 +138,8 @@ static esp_err_t verify_host_fingerprint(ts_ssh_session_t session, /* 获取验证参数 */ const cJSON *trust_new_j = cJSON_GetObjectItem(params, "trust_new"); const cJSON *accept_changed_j = cJSON_GetObjectItem(params, "accept_changed"); - - bool trust_new = cJSON_IsBool(trust_new_j) ? cJSON_IsTrue(trust_new_j) : true; + + bool trust_new = cJSON_IsBool(trust_new_j) ? cJSON_IsTrue(trust_new_j) : false; bool accept_changed = cJSON_IsBool(accept_changed_j) ? cJSON_IsTrue(accept_changed_j) : false; /* 验证主机指纹 */ @@ -166,7 +151,13 @@ static esp_err_t verify_host_fingerprint(ts_ssh_session_t session, ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to verify host fingerprint"); return ret; } - + + const cJSON *confirmed = cJSON_GetObjectItem(params, "confirmed_fingerprint"); + bool confirmed_match = + cJSON_IsString(confirmed) && !strcmp(confirmed->valuestring, host_info.fingerprint); + trust_new = trust_new && confirmed_match; + accept_changed = accept_changed && confirmed_match; + /* 输出主机信息 */ if (host_info_out) { *host_info_out = host_info; @@ -247,6 +238,20 @@ static esp_err_t verify_host_fingerprint(ts_ssh_session_t session, } } +typedef struct { + const cJSON *params; + ts_api_result_t *result; +} verify_context_t; +static esp_err_t verify_before_auth(ts_ssh_session_t session, void *opaque) { + verify_context_t *ctx = opaque; + return verify_host_fingerprint(session, ctx->params, ctx->result, NULL); +} +static esp_err_t connect_verified(ts_ssh_session_t session, const cJSON *params, + ts_api_result_t *result) { + verify_context_t ctx = {params, result}; + return ts_ssh_connect_with_verifier(session, verify_before_auth, &ctx); +} + /*===========================================================================*/ /* API Handlers */ /*===========================================================================*/ @@ -282,6 +287,7 @@ static esp_err_t verify_host_fingerprint(ts_ssh_session_t session, */ static esp_err_t api_ssh_exec(const cJSON *params, ts_api_result_t *result) { + ssh_request_key_t request_key __attribute__((cleanup(cleanup_key_buffer))) = {0}; if (!params) { ts_api_result_error(result, TS_API_ERR_INVALID_ARG, "Missing parameters"); return ESP_ERR_INVALID_ARG; @@ -295,10 +301,10 @@ static esp_err_t api_ssh_exec(const cJSON *params, ts_api_result_t *result) /* 配置 SSH */ ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); - esp_err_t ret = configure_ssh_from_params(params, &config); + esp_err_t ret = configure_ssh_from_params(params, &config, &request_key); if (ret != ESP_OK) { ts_api_result_error(result, TS_API_ERR_INVALID_ARG, "Invalid SSH configuration"); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ret; } @@ -313,17 +319,18 @@ static esp_err_t api_ssh_exec(const cJSON *params, ts_api_result_t *result) ret = ts_ssh_session_create(&config, &session); if (ret != ESP_OK) { ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to create session"); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ret; } /* 连接(TCP 层) */ - ret = ts_ssh_connect(session); + ret = connect_verified(session, params, result); if (ret != ESP_OK) { const char *err = ts_ssh_get_error(session); - ts_api_result_error(result, TS_API_ERR_CONNECTION, err ? err : "Failed to connect"); + if (result->code == TS_API_OK) + ts_api_result_error(result, TS_API_ERR_CONNECTION, err ? err : "Failed to connect"); ts_ssh_session_destroy(session); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ret; } @@ -334,7 +341,7 @@ static esp_err_t api_ssh_exec(const cJSON *params, ts_api_result_t *result) /* result 已在 verify_host_fingerprint 中设置 */ ts_ssh_disconnect(session); ts_ssh_session_destroy(session); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ret; } @@ -370,8 +377,8 @@ static esp_err_t api_ssh_exec(const cJSON *params, ts_api_result_t *result) ts_ssh_disconnect(session); ts_ssh_session_destroy(session); - cleanup_key_buffer(); - + cleanup_key_buffer(&request_key); + return ret; } @@ -538,24 +545,19 @@ static esp_err_t api_ssh_cancel(const cJSON *params, ts_api_result_t *result) { const cJSON *sid = cJSON_GetObjectItem(params, "session_id"); - uint32_t session_id = 0; - if (sid && cJSON_IsNumber(sid)) { - session_id = (uint32_t)sid->valueint; - } - - /* 检查会话是否在运行 */ - if (!ts_webui_ssh_exec_is_running(session_id)) { + /* Exact instance identity; a status wildcard is never a control target. */ + if (!cJSON_IsNumber(sid) || sid->valuedouble < 1 || sid->valuedouble > UINT32_MAX || + sid->valuedouble != (double)(uint32_t)sid->valuedouble) { ts_api_result_error(result, TS_API_ERR_NOT_FOUND, "No running session"); return ESP_ERR_NOT_FOUND; } - - /* 取消执行 */ - esp_err_t ret = ts_webui_ssh_exec_cancel(session_id); + esp_err_t ret = ts_webui_ssh_exec_cancel((uint32_t)sid->valuedouble); if (ret != ESP_OK) { - ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to cancel"); + ts_api_result_error(result, ret == ESP_ERR_INVALID_STATE ? TS_API_ERR_NOT_FOUND : TS_API_ERR_INTERNAL, + ret == ESP_ERR_INVALID_STATE ? "No running session" : "Failed to request cancellation"); return ret; } - + /* Existing wire field means accepted intent, not confirmed remote exit. */ cJSON *data = cJSON_CreateObject(); cJSON_AddBoolToObject(data, "cancelled", true); ts_api_result_ok(result, data); @@ -586,6 +588,7 @@ static esp_err_t api_ssh_cancel(const cJSON *params, ts_api_result_t *result) */ static esp_err_t api_ssh_test(const cJSON *params, ts_api_result_t *result) { + ssh_request_key_t request_key __attribute__((cleanup(cleanup_key_buffer))) = {0}; if (!params) { ts_api_result_error(result, TS_API_ERR_INVALID_ARG, "Missing parameters"); return ESP_ERR_INVALID_ARG; @@ -593,10 +596,10 @@ static esp_err_t api_ssh_test(const cJSON *params, ts_api_result_t *result) /* 配置 SSH */ ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); - esp_err_t ret = configure_ssh_from_params(params, &config); + esp_err_t ret = configure_ssh_from_params(params, &config, &request_key); if (ret != ESP_OK) { ts_api_result_error(result, TS_API_ERR_INVALID_ARG, "Invalid SSH configuration"); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ret; } @@ -605,21 +608,26 @@ static esp_err_t api_ssh_test(const cJSON *params, ts_api_result_t *result) ret = ts_ssh_session_create(&config, &session); if (ret != ESP_OK) { ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to create session"); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ret; } /* 测试连接(TCP 层) */ - ret = ts_ssh_connect(session); - + ret = connect_verified(session, params, result); + if (ret != ESP_OK) { + if (result->code != TS_API_OK) { + ts_ssh_session_destroy(session); + cleanup_key_buffer(&request_key); + return ESP_OK; + } const char *err = ts_ssh_get_error(session); cJSON *data = cJSON_CreateObject(); cJSON_AddBoolToObject(data, "success", false); cJSON_AddStringToObject(data, "error", err ? err : "Connection failed"); ts_api_result_ok(result, data); ts_ssh_session_destroy(session); - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); return ESP_OK; } @@ -633,8 +641,8 @@ static esp_err_t api_ssh_test(const cJSON *params, ts_api_result_t *result) */ ts_ssh_disconnect(session); ts_ssh_session_destroy(session); - cleanup_key_buffer(); - + cleanup_key_buffer(&request_key); + /* 如果是 MISMATCH 或 NEW_HOST,返回 ESP_OK 让 HTTP 层返回 200 * 实际错误信息已在 result 中设置 */ if (result->code == TS_API_ERR_HOST_MISMATCH || @@ -655,8 +663,8 @@ static esp_err_t api_ssh_test(const cJSON *params, ts_api_result_t *result) ts_ssh_disconnect(session); ts_ssh_session_destroy(session); - cleanup_key_buffer(); - + cleanup_key_buffer(&request_key); + ts_api_result_ok(result, data); return ESP_OK; } @@ -684,6 +692,7 @@ static esp_err_t api_ssh_test(const cJSON *params, ts_api_result_t *result) */ static esp_err_t api_ssh_copyid(const cJSON *params, ts_api_result_t *result) { + ssh_request_key_t request_key __attribute__((cleanup(cleanup_key_buffer))) = {0}; if (!params) { ts_api_result_error(result, TS_API_ERR_INVALID_ARG, "Missing parameters"); return ESP_ERR_INVALID_ARG; @@ -728,16 +737,13 @@ static esp_err_t api_ssh_copyid(const cJSON *params, ts_api_result_t *result) /* 配置 SSH 连接(使用密码认证) */ ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); - strncpy(s_host_buf, host->valuestring, sizeof(s_host_buf) - 1); - strncpy(s_user_buf, user->valuestring, sizeof(s_user_buf) - 1); - strncpy(s_pass_buf, password->valuestring, sizeof(s_pass_buf) - 1); - - config.host = s_host_buf; + + config.host = host->valuestring; config.port = ssh_port; - config.username = s_user_buf; + config.username = user->valuestring; config.auth_method = TS_SSH_AUTH_PASSWORD; - config.auth.password = s_pass_buf; - + config.auth.password = password->valuestring; + /* 创建会话并连接 */ ts_ssh_session_t session = NULL; ret = ts_ssh_session_create(&config, &session); @@ -746,11 +752,12 @@ static esp_err_t api_ssh_copyid(const cJSON *params, ts_api_result_t *result) free(pubkey_data); return ret; } - - ret = ts_ssh_connect(session); + + ret = connect_verified(session, params, result); if (ret != ESP_OK) { const char *err = ts_ssh_get_error(session); - ts_api_result_error(result, TS_API_ERR_CONNECTION, err ? err : "Failed to connect"); + if (result->code == TS_API_OK) + ts_api_result_error(result, TS_API_ERR_CONNECTION, err ? err : "Failed to connect"); ts_ssh_session_destroy(session); free(pubkey_data); return ret; @@ -813,18 +820,18 @@ static esp_err_t api_ssh_copyid(const cJSON *params, ts_api_result_t *result) bool verified = false; if (do_verify) { /* 加载私钥 */ - cleanup_key_buffer(); - ret = ts_keystore_load_private_key(keyid->valuestring, &s_key_buf, &s_key_len); + cleanup_key_buffer(&request_key); + ret = ts_keystore_load_private_key(keyid->valuestring, &request_key.data, &request_key.len); if (ret == ESP_OK) { /* 使用公钥认证重新连接 */ ts_ssh_config_t verify_config = TS_SSH_DEFAULT_CONFIG(); - verify_config.host = s_host_buf; + verify_config.host = host->valuestring; verify_config.port = ssh_port; - verify_config.username = s_user_buf; + verify_config.username = user->valuestring; verify_config.auth_method = TS_SSH_AUTH_PUBLICKEY; - verify_config.auth.key.private_key = (const uint8_t *)s_key_buf; - verify_config.auth.key.private_key_len = s_key_len; - + verify_config.auth.key.private_key = (const uint8_t *)request_key.data; + verify_config.auth.key.private_key_len = request_key.len; + ts_ssh_session_t verify_session = NULL; if (ts_ssh_session_create(&verify_config, &verify_session) == ESP_OK) { if (ts_ssh_connect(verify_session) == ESP_OK) { @@ -833,7 +840,7 @@ static esp_err_t api_ssh_copyid(const cJSON *params, ts_api_result_t *result) } ts_ssh_session_destroy(verify_session); } - cleanup_key_buffer(); + cleanup_key_buffer(&request_key); } } @@ -962,16 +969,13 @@ static esp_err_t api_ssh_revoke(const cJSON *params, ts_api_result_t *result) /* 配置 SSH 连接(使用密码认证) */ ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); - strncpy(s_host_buf, host->valuestring, sizeof(s_host_buf) - 1); - strncpy(s_user_buf, user->valuestring, sizeof(s_user_buf) - 1); - strncpy(s_pass_buf, password->valuestring, sizeof(s_pass_buf) - 1); - - config.host = s_host_buf; + + config.host = host->valuestring; config.port = ssh_port; - config.username = s_user_buf; + config.username = user->valuestring; config.auth_method = TS_SSH_AUTH_PASSWORD; - config.auth.password = s_pass_buf; - + config.auth.password = password->valuestring; + /* 创建会话并连接 */ ts_ssh_session_t session = NULL; ret = ts_ssh_session_create(&config, &session); @@ -981,11 +985,12 @@ static esp_err_t api_ssh_revoke(const cJSON *params, ts_api_result_t *result) free(pubkey_copy); return ret; } - - ret = ts_ssh_connect(session); + + ret = connect_verified(session, params, result); if (ret != ESP_OK) { const char *err = ts_ssh_get_error(session); - ts_api_result_error(result, TS_API_ERR_CONNECTION, err ? err : "Failed to connect"); + if (result->code == TS_API_OK) + ts_api_result_error(result, TS_API_ERR_CONNECTION, err ? err : "Failed to connect"); ts_ssh_session_destroy(session); free(pubkey_data); free(pubkey_copy); diff --git a/components/ts_automation/CMakeLists.txt b/components/ts_automation/CMakeLists.txt index 0a65f34..efba37f 100644 --- a/components/ts_automation/CMakeLists.txt +++ b/components/ts_automation/CMakeLists.txt @@ -4,6 +4,8 @@ idf_component_register( "src/ts_variable.c" "src/ts_source_manager.c" "src/ts_rule_engine.c" + "src/ts_rule_codec.c" + "src/ts_rule_store.c" "src/ts_action_manager.c" INCLUDE_DIRS "include" diff --git a/components/ts_automation/include/ts_action_manager.h b/components/ts_automation/include/ts_action_manager.h index 1709342..27e3c0f 100644 --- a/components/ts_automation/include/ts_action_manager.h +++ b/components/ts_automation/include/ts_action_manager.h @@ -105,6 +105,7 @@ typedef struct { uint8_t priority; /**< Priority (0=highest) */ int64_t enqueue_time; /**< When queued */ /* Sync execution support */ + void *completion; /**< Shared completion lifetime, independent of waiter stack. */ SemaphoreHandle_t done_sem; /**< Signaled when done (sync mode) */ ts_action_result_t *result_ptr; /**< Where to store result (sync mode) */ } ts_action_queue_entry_t; @@ -147,6 +148,9 @@ esp_err_t ts_action_manager_init(void); * @return ESP_OK on success */ esp_err_t ts_action_manager_deinit(void); +esp_err_t ts_action_manager_quiesce(void); +bool ts_action_manager_accepting(void); +esp_err_t ts_action_manager_resume(void); /** * @brief Check if action manager is initialized @@ -524,6 +528,12 @@ esp_err_t ts_action_templates_load(void); */ esp_err_t ts_action_templates_load_from_file(const char *filepath); +/* Only actual admissions allocate snapshots; ordinary condition evaluation does not. */ +esp_err_t ts_action_snapshot(const ts_auto_action_t *source, ts_auto_action_t *out); +void ts_action_snapshot_owner(const ts_auto_action_t *action, const char *rule); +void ts_action_snapshot_retain(const ts_auto_action_t *action); +void ts_action_snapshot_release(ts_auto_action_t *action); + #ifdef __cplusplus } #endif diff --git a/components/ts_automation/include/ts_automation_types.h b/components/ts_automation/include/ts_automation_types.h index 55f1d39..9de43aa 100644 --- a/components/ts_automation/include/ts_automation_types.h +++ b/components/ts_automation/include/ts_automation_types.h @@ -287,6 +287,7 @@ typedef enum { TS_AUTO_ACT_DEVICE_CTRL, /**< Device control - deprecated, use CLI */ TS_AUTO_ACT_SSH_CMD_REF, /**< SSH command reference (from registered commands) */ TS_AUTO_ACT_CLI, /**< TianShanOS CLI command execution */ + TS_AUTO_ACT_TEMPLATE_REF, /**< Unresolved template-only reference; never execute directly. */ } ts_auto_action_type_t; /** @@ -442,6 +443,8 @@ typedef struct { ts_auto_action_condition_t condition; /**< Execute only if condition is met */ /* Template reference (for rule actions) */ + bool runtime_snapshot; /**< Execution-only; never serialized. */ + void *runtime_binding; /**< Owned execution snapshot; never serialized. */ char template_id[TS_AUTO_NAME_MAX_LEN]; /**< Source template ID (optional, for tracing) */ union { @@ -465,7 +468,14 @@ typedef struct { char name[TS_AUTO_LABEL_MAX_LEN]; /**< Display name */ char icon[64]; /**< Display icon (emoji or /sdcard/images/xxx.png) */ bool enabled; /**< Is rule enabled */ - bool manual_trigger; /**< Can be manually triggered from UI */ + bool manual_trigger; /**< Exclude from automatic evaluation */ + bool show_on_dashboard; + bool allow_manual_trigger; + uint8_t presentation_fields; /**< bit 0: show present; bit 1: allow present */ + bool reference_unresolved; + uint32_t revision; + uint32_t instance; + void *lease; /**< Internal read ownership, never persisted */ uint32_t cooldown_ms; /**< Min time between triggers */ ts_auto_condition_group_t conditions; /**< Trigger conditions */ diff --git a/components/ts_automation/include/ts_rule_codec.h b/components/ts_automation/include/ts_rule_codec.h new file mode 100644 index 0000000..24aea38 --- /dev/null +++ b/components/ts_automation/include/ts_rule_codec.h @@ -0,0 +1,14 @@ +#pragma once +#include "ts_automation_types.h" +#include "cJSON.h" +#ifdef __cplusplus +extern "C" { +#endif +/* Decode owns arrays. Dispose decoded values; release engine reads separately. */ +esp_err_t ts_rule_decode(const cJSON *json, ts_auto_rule_t *rule); +cJSON *ts_rule_encode(const ts_auto_rule_t *rule); +void ts_rule_dispose(ts_auto_rule_t *rule); +bool ts_rule_id_valid(const char *id); +#ifdef __cplusplus +} +#endif diff --git a/components/ts_automation/include/ts_rule_engine.h b/components/ts_automation/include/ts_rule_engine.h index d6e5378..43f555c 100644 --- a/components/ts_automation/include/ts_rule_engine.h +++ b/components/ts_automation/include/ts_rule_engine.h @@ -83,7 +83,10 @@ esp_err_t ts_rule_disable(const char *id); * @param id Rule ID * @return Rule pointer or NULL */ -const ts_auto_rule_t *ts_rule_get(const char *id); +typedef struct {int applied,durable,mirror_synced;uint32_t revision;const char *error_code;} ts_rule_commit_result_t; +esp_err_t ts_rule_acquire(const char *id,ts_auto_rule_t *out); +void ts_rule_release(ts_auto_rule_t *rule); +esp_err_t ts_rule_commit(const ts_auto_rule_t *candidate,const char *id,uint32_t expected_revision,ts_rule_commit_result_t *result); /** * @brief Get number of registered rules @@ -185,7 +188,7 @@ esp_err_t ts_action_execute_array(const ts_auto_action_t *actions, int count, * @brief Get rule by index * * @param index Rule index (0 to rule_count-1) - * @param rule Output rule structure + * @param rule Pinned output; caller MUST ts_rule_release after use * @return ESP_OK on success, ESP_ERR_NOT_FOUND if index out of range */ esp_err_t ts_rule_get_by_index(int index, ts_auto_rule_t *rule); @@ -346,6 +349,12 @@ esp_err_t ts_rules_load(void); */ esp_err_t ts_rules_load_from_file(const char *filepath); +/* Cold API/load path only: may allocate and resolve command/template references. */ +void ts_rule_resolve_presentation(ts_auto_rule_t *rule); +bool ts_rule_edit_begin(void); +void ts_rule_edit_end(void); +void ts_rule_config_status(bool *loaded, bool *recovery); + #ifdef __cplusplus } #endif diff --git a/components/ts_automation/src/ts_action_manager.c b/components/ts_automation/src/ts_action_manager.c index 429901c..b6ed64c 100644 --- a/components/ts_automation/src/ts_action_manager.c +++ b/components/ts_automation/src/ts_action_manager.c @@ -1,3 +1,6 @@ +#include "ts_ssh_probe.h" +#include "ts_ssh_service.h" +#include /** * @file ts_action_manager.c * @brief TianShanOS Automation Engine - Action Manager Implementation @@ -101,8 +104,10 @@ typedef struct { /* Action queue */ QueueHandle_t action_queue; TaskHandle_t executor_task; - bool running; - + atomic_bool running; + atomic_bool accepting; + unsigned pending; /* producers + queued + executing, protected by stats_mutex */ + /* Statistics */ ts_action_stats_t stats; SemaphoreHandle_t stats_mutex; @@ -113,6 +118,100 @@ typedef struct { static action_manager_ctx_t *s_ctx = NULL; +typedef struct { + atomic_uint refs; + ts_ssh_command_config_t command; + ts_action_ssh_host_t host; + bool pinned; + uint32_t registration; +} action_binding_t; +typedef struct { + atomic_uint refs; + SemaphoreHandle_t semaphore; + ts_action_result_t result; +} action_completion_t; +static void completion_release(action_completion_t *c) { + if (c && atomic_fetch_sub(&c->refs, 1) == 1) { + vSemaphoreDelete(c->semaphore); + free(c); + } +} +void ts_action_snapshot_owner(const ts_auto_action_t *a, const char *rule) { + action_binding_t *b = a->runtime_binding; + if (b && b->pinned) ts_ssh_service_set_owner(b->command.id, b->registration, rule); +} +void ts_action_snapshot_retain(const ts_auto_action_t *a) { + if (a && a->runtime_binding) + atomic_fetch_add(&((action_binding_t *)a->runtime_binding)->refs, 1); +} +void ts_action_snapshot_release(ts_auto_action_t *a) { + action_binding_t *b = a ? a->runtime_binding : NULL; + if (b && atomic_fetch_sub(&b->refs, 1) == 1) { + if (b->pinned) + ts_ssh_service_unpin(b->command.id, b->registration); + memset(b->host.password, 0, sizeof(b->host.password)); + free(b); + } + if (a) + a->runtime_binding = NULL; +} +esp_err_t ts_action_snapshot(const ts_auto_action_t *source, ts_auto_action_t *out) { + *out = *source; + out->runtime_binding = NULL; + out->runtime_snapshot = true; + if (source->template_id[0]) { + ts_action_template_t *tpl = + heap_caps_malloc(sizeof(*tpl), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!tpl) + return ESP_ERR_NO_MEM; + esp_err_t ret = ts_action_template_get(source->template_id, tpl); + if (ret == ESP_OK && !tpl->enabled) + ret = ESP_ERR_INVALID_STATE; + if (ret == ESP_OK) { + *out = tpl->action; + out->async |= tpl->async; + out->delay_ms = source->delay_ms; + out->repeat_mode = source->repeat_mode; + out->repeat_count = source->repeat_count; + out->repeat_interval_ms = source->repeat_interval_ms; + out->condition = source->condition; + out->template_id[0] = 0; + out->runtime_binding = NULL; + out->runtime_snapshot = true; + } + free(tpl); + if (ret != ESP_OK) + return ret; + } + if (out->type != TS_AUTO_ACT_SSH_CMD_REF) + return ESP_OK; + if (!source->template_id[0] && !source->runtime_snapshot) + out->async = true; + action_binding_t *binding = + heap_caps_calloc(1, sizeof(*binding), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!binding) + return ESP_ERR_NO_MEM; + atomic_init(&binding->refs, 1); + esp_err_t ret = ts_ssh_commands_config_get(out->ssh_ref.cmd_id, &binding->command); + if (ret == ESP_OK) + ret = ts_action_get_ssh_host(binding->command.host_id, &binding->host); + if (ret == ESP_OK && !binding->command.enabled) + ret = ESP_ERR_INVALID_STATE; + if (ret == ESP_OK && binding->command.nohup && binding->command.service_mode) { + if (!ts_ssh_service_start_admissible(binding->command.id)) + ret = ESP_ERR_INVALID_STATE; + else { + ret = ts_ssh_service_pin(&binding->command, binding->host.host, binding->host.port, &binding->registration); + binding->pinned = ret == ESP_OK; + } + } + if (ret != ESP_OK) { + free(binding); + return ret; + } + out->runtime_binding = binding; + return ESP_OK; +} /*===========================================================================*/ /* Forward Declarations */ /*===========================================================================*/ @@ -165,6 +264,7 @@ esp_err_t ts_action_manager_init(void) * Use xTaskCreateWithCaps to explicitly allocate stack in DRAM. */ s_ctx->running = true; + s_ctx->accepting = true; BaseType_t ret = xTaskCreateWithCaps(action_executor_task, "action_exec", ACTION_TASK_STACK_SIZE, @@ -235,20 +335,24 @@ void ts_action_deferred_load_task(void *arg) esp_err_t ts_action_manager_deinit(void) { if (s_ctx == NULL) { - return ESP_ERR_INVALID_STATE; + return ESP_OK; } ESP_LOGI(TAG, "Deinitializing action manager"); - /* Stop executor task */ + /* Admission stays closed until every producer/executor has released ownership. */ + if (ts_action_manager_quiesce() != ESP_OK) return ESP_ERR_TIMEOUT; s_ctx->running = false; - if (s_ctx->executor_task) { - /* Send empty entry to wake up task */ - ts_action_queue_entry_t empty = {0}; - xQueueSend(s_ctx->action_queue, &empty, 0); - vTaskDelay(pdMS_TO_TICKS(100)); + xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); + bool exiting = s_ctx->executor_task != NULL; + xSemaphoreGive(s_ctx->stats_mutex); + if (exiting) { + /* Queue receive has a bounded timeout; no fake entry owns a pending credit. */ + /* Cooperative stop requested; cleanup requires a later call after exit. */ + return ESP_ERR_INVALID_STATE; } - + + ts_action_cancel_all(); /* Cleanup resources */ if (s_ctx->action_queue) vQueueDelete(s_ctx->action_queue); if (s_ctx->ssh_hosts_mutex) vSemaphoreDelete(s_ctx->ssh_hosts_mutex); @@ -420,63 +524,90 @@ esp_err_t ts_action_get_ssh_hosts(ts_action_ssh_host_t *hosts_out, * the action executes in the executor task context, which has a DRAM stack * and can safely perform NVS/Flash operations. */ -esp_err_t ts_action_manager_execute(const ts_auto_action_t *action, - ts_action_result_t *result) -{ - if (!s_ctx || !action) { - return ESP_ERR_INVALID_ARG; - } - - if (!s_ctx->running || !s_ctx->executor_task) { - ESP_LOGE(TAG, "Executor task not running"); +static bool action_admit(void) { + xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); + bool accept = s_ctx->running && s_ctx->accepting; + if (accept) s_ctx->pending += 2; /* caller + queue/executor ownership */ + xSemaphoreGive(s_ctx->stats_mutex); + return accept; +} +static void action_finished(void) { + xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); + --s_ctx->pending; + xSemaphoreGive(s_ctx->stats_mutex); +} +bool ts_action_manager_accepting(void) { return s_ctx && s_ctx->accepting; } +esp_err_t ts_action_manager_quiesce(void) { + if (!s_ctx) return ESP_OK; + xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); + s_ctx->accepting = false; + bool idle = s_ctx->pending == 0; + xSemaphoreGive(s_ctx->stats_mutex); + return idle ? ESP_OK : ESP_ERR_TIMEOUT; +} +esp_err_t ts_action_manager_resume(void) { + if (!s_ctx) return ESP_ERR_INVALID_STATE; + xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); + bool idle = s_ctx->running && !s_ctx->pending; + if (idle) s_ctx->accepting = true; + xSemaphoreGive(s_ctx->stats_mutex); + return idle ? ESP_OK : ESP_ERR_INVALID_STATE; +} +esp_err_t ts_action_manager_execute(const ts_auto_action_t *action, ts_action_result_t *result) { + if (!s_ctx || !action || !s_ctx->running || !s_ctx->executor_task) return ESP_ERR_INVALID_STATE; - } - - ts_action_result_t local_result = {0}; - ts_action_result_t *res = result ? result : &local_result; - - /* Create semaphore for sync execution */ - SemaphoreHandle_t done_sem = xSemaphoreCreateBinary(); - if (!done_sem) { - ESP_LOGE(TAG, "Failed to create sync semaphore"); + if (!action_admit()) return ESP_ERR_INVALID_STATE; + action_completion_t *c = heap_caps_calloc(1, sizeof(*c), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!c) { action_finished(); action_finished(); return ESP_ERR_NO_MEM; } + c->semaphore = xSemaphoreCreateBinary(); + if (!c->semaphore) { + free(c); + action_finished(); action_finished(); return ESP_ERR_NO_MEM; } - - /* Queue the action with sync fields */ + atomic_init(&c->refs, 2); + ts_auto_action_t frozen; + esp_err_t ret = ESP_OK; + if (action->runtime_snapshot) { + frozen = *action; + ts_action_snapshot_retain(&frozen); + } else { + ts_ssh_binding_lock(); + ret = ts_action_snapshot(action, &frozen); + ts_ssh_binding_unlock(); + } + if (ret != ESP_OK) { + completion_release(c); + completion_release(c); + action_finished(); action_finished(); + return ret; + } ts_action_queue_entry_t entry = { - .action = *action, - .callback = NULL, - .user_data = NULL, - .priority = 0, - .enqueue_time = esp_timer_get_time() / 1000, - .done_sem = done_sem, - .result_ptr = res - }; - + .action = frozen, .completion = c, .done_sem = c->semaphore, .result_ptr = &c->result}; if (xQueueSend(s_ctx->action_queue, &entry, pdMS_TO_TICKS(100)) != pdTRUE) { - ESP_LOGW(TAG, "Action queue full"); - vSemaphoreDelete(done_sem); + ts_action_snapshot_release(&frozen); + completion_release(c); + completion_release(c); + action_finished(); action_finished(); return ESP_ERR_NO_MEM; } - - /* Wait for completion (timeout based on action type) */ - uint32_t timeout_ms = 30000; /* Default 30s */ - if (action->type == TS_AUTO_ACT_SSH_CMD || action->type == TS_AUTO_ACT_SSH_CMD_REF) { - timeout_ms = 60000; /* SSH commands may take longer */ - } - - if (xSemaphoreTake(done_sem, pdMS_TO_TICKS(timeout_ms)) != pdTRUE) { - ESP_LOGE(TAG, "Action execution timeout"); - res->status = TS_ACTION_STATUS_TIMEOUT; - snprintf(res->output, sizeof(res->output), "Execution timeout"); - vSemaphoreDelete(done_sem); - return ESP_ERR_TIMEOUT; + uint32_t timeout = + action->type == TS_AUTO_ACT_SSH_CMD || action->type == TS_AUTO_ACT_SSH_CMD_REF ? 60000 + : 30000; + if (xSemaphoreTake(c->semaphore, pdMS_TO_TICKS(timeout)) != pdTRUE) { + if (result) { + memset(result, 0, sizeof(*result)); + result->status = TS_ACTION_STATUS_TIMEOUT; + } + ret = ESP_ERR_TIMEOUT; + } else { + if (result) + *result = c->result; + ret = c->result.status == TS_ACTION_STATUS_SUCCESS ? ESP_OK : ESP_FAIL; } - - vSemaphoreDelete(done_sem); - - /* Stats are updated by executor task */ - return (res->status == TS_ACTION_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; + completion_release(c); + action_finished(); /* caller releases only its own credit */ + return ret; } esp_err_t ts_action_queue(const ts_auto_action_t *action, @@ -484,22 +615,35 @@ esp_err_t ts_action_queue(const ts_auto_action_t *action, void *user_data, uint8_t priority) { - if (!s_ctx || !action) { + if (!s_ctx || !s_ctx->running || !action) { return ESP_ERR_INVALID_ARG; } - + + if (!action_admit()) return ESP_ERR_INVALID_STATE; + ts_auto_action_t frozen; + if (action->runtime_snapshot) { + frozen = *action; + ts_action_snapshot_retain(&frozen); + } else { + ts_ssh_binding_lock(); + esp_err_t ret = ts_action_snapshot(action, &frozen); + ts_ssh_binding_unlock(); + if (ret != ESP_OK) { action_finished(); action_finished(); return ret; } + } ts_action_queue_entry_t entry = { - .action = *action, + .action = frozen, .callback = callback, .user_data = user_data, .priority = priority, .enqueue_time = esp_timer_get_time() / 1000, - .done_sem = NULL, /* Async mode: no sync semaphore */ - .result_ptr = NULL /* Async mode: no result pointer */ + .done_sem = NULL, /* Async mode: no sync semaphore */ + .result_ptr = NULL /* Async mode: no result pointer */ }; - + if (xQueueSend(s_ctx->action_queue, &entry, pdMS_TO_TICKS(100)) != pdTRUE) { + ts_action_snapshot_release(&frozen); ESP_LOGW(TAG, "Action queue full"); + action_finished(); action_finished(); return ESP_ERR_NO_MEM; } @@ -510,7 +654,7 @@ esp_err_t ts_action_queue(const ts_auto_action_t *action, s_ctx->stats.queue_high_water = waiting; } xSemaphoreGive(s_ctx->stats_mutex); - + action_finished(); return ESP_OK; } @@ -528,7 +672,7 @@ esp_err_t ts_action_execute_sequence(const ts_auto_action_t *actions, for (int i = 0; i < count; i++) { ret = ts_action_manager_execute(&actions[i], &result); if (ret != ESP_OK || result.status != TS_ACTION_STATUS_SUCCESS) { - ESP_LOGW(TAG, "Action %d failed: %s", i, result.output); + ESP_LOGW(TAG, "Action %d failed (code=%d)", i, ret); if (stop_on_error) { return ret != ESP_OK ? ret : ESP_FAIL; } @@ -545,7 +689,16 @@ esp_err_t ts_action_cancel_all(void) } /* Clear queue */ - xQueueReset(s_ctx->action_queue); + ts_action_queue_entry_t entry; + while (xQueueReceive(s_ctx->action_queue, &entry, 0) == pdTRUE) { + ts_action_snapshot_release(&entry.action); + if (entry.result_ptr) + entry.result_ptr->status = TS_ACTION_STATUS_CANCELLED; + if (entry.done_sem) + xSemaphoreGive(entry.done_sem); + completion_release(entry.completion); + action_finished(); + } ESP_LOGI(TAG, "Cancelled all pending actions"); return ESP_OK; } @@ -586,9 +739,9 @@ esp_err_t ts_action_exec_ssh(const ts_auto_action_ssh_t *ssh, return ESP_ERR_NO_MEM; } ts_action_expand_variables(ssh->command, expanded_cmd, TS_SSH_CMD_COMMAND_MAX); - - ESP_LOGI(TAG, "SSH [%s]: %s", ssh->host_ref, expanded_cmd); - + + ESP_LOGD(TAG, "SSH host=%s, command bytes=%u", ssh->host_ref, (unsigned)strlen(expanded_cmd)); + /* Create SSH session */ ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); config.host = host.host; @@ -599,6 +752,7 @@ esp_err_t ts_action_exec_ssh(const ts_auto_action_ssh_t *ssh, /* Load SSH key from keystore if using key auth */ char *key_data = NULL; size_t key_len = 0; + char full_path[128] = {0}; esp_err_t ret; if (host.use_key_auth && host.key_path[0]) { @@ -615,7 +769,6 @@ esp_err_t ts_action_exec_ssh(const ts_auto_action_ssh_t *ssh, ESP_LOGI(TAG, "Loaded SSH key '%s' from keystore (%zu bytes)", keyid, key_len); } else { /* Fallback: try as file path */ - char full_path[128]; if (keyid[0] == '/') { strncpy(full_path, keyid, sizeof(full_path) - 1); } else { @@ -678,8 +831,7 @@ esp_err_t ts_action_exec_ssh(const ts_auto_action_ssh_t *ssh, : TS_ACTION_STATUS_FAILED; /* Free result strings */ - if (exec_result.stdout_data) free(exec_result.stdout_data); - if (exec_result.stderr_data) free(exec_result.stderr_data); + ts_ssh_exec_result_free(&exec_result); } else { snprintf(result->output, sizeof(result->output), "SSH exec failed: %s", esp_err_to_name(ret)); @@ -687,7 +839,8 @@ esp_err_t ts_action_exec_ssh(const ts_auto_action_ssh_t *ssh, ? TS_ACTION_STATUS_TIMEOUT : TS_ACTION_STATUS_FAILED; } - + + ts_ssh_exec_result_free(&exec_result); /* Cleanup */ ts_ssh_disconnect(session); ts_ssh_session_destroy(session); @@ -873,8 +1026,8 @@ esp_err_t ts_action_exec_led(const ts_auto_action_led_t *led, if (led_final->speed > 0) { len += snprintf(cmd + len, sizeof(cmd) - len, " --speed %d", led_final->speed); } - - ESP_LOGI(TAG, "Executing LED text CLI: %s", cmd); + + ESP_LOGD(TAG, "Executing LED CLI (%u bytes)", (unsigned)strlen(cmd)); ret = ts_console_exec(cmd, NULL); snprintf(result->output, sizeof(result->output), "LED text: %.200s%s", led_final->text, strlen(led_final->text) > 200 ? "..." : ""); } else { @@ -894,8 +1047,8 @@ esp_err_t ts_action_exec_led(const ts_auto_action_led_t *led, char cmd[512]; snprintf(cmd, sizeof(cmd), "led --image --device matrix --file %.256s%s", led_final->image_path, led_final->center ? " --center content" : ""); - - ESP_LOGI(TAG, "Executing LED image CLI: %s", cmd); + + ESP_LOGD(TAG, "Executing LED CLI (%u bytes)", (unsigned)strlen(cmd)); ret = ts_console_exec(cmd, NULL); snprintf(result->output, sizeof(result->output), "LED image: %.200s%s", led_final->image_path, strlen(led_final->image_path) > 200 ? "..." : ""); } else { @@ -920,8 +1073,8 @@ esp_err_t ts_action_exec_led(const ts_auto_action_led_t *led, if (led_final->r || led_final->g || led_final->b) { len += snprintf(cmd + len, sizeof(cmd) - len, " --color #%02X%02X%02X", led_final->r, led_final->g, led_final->b); } - - ESP_LOGI(TAG, "Executing LED QR CLI: %s", cmd); + + ESP_LOGD(TAG, "Executing LED CLI (%u bytes)", (unsigned)strlen(cmd)); ret = ts_console_exec(cmd, NULL); snprintf(result->output, sizeof(result->output), "LED QR: %.200s%s", led_final->qr_text, strlen(led_final->qr_text) > 200 ? "..." : ""); @@ -945,8 +1098,8 @@ esp_err_t ts_action_exec_led(const ts_auto_action_led_t *led, } else { snprintf(cmd, sizeof(cmd), "led --filter --device matrix --filter-name %s", led_final->filter); } - - ESP_LOGI(TAG, "Executing LED filter CLI: %s", cmd); + + ESP_LOGD(TAG, "Executing LED CLI (%u bytes)", (unsigned)strlen(cmd)); ret = ts_console_exec(cmd, NULL); snprintf(result->output, sizeof(result->output), "LED filter: %s", led_final->filter); } else { @@ -964,7 +1117,7 @@ esp_err_t ts_action_exec_led(const ts_auto_action_led_t *led, } { const char *cmd = "led --stop-filter --device matrix"; - ESP_LOGI(TAG, "Executing LED filter stop CLI: %s", cmd); + ESP_LOGD(TAG, "Executing LED CLI (%u bytes)", (unsigned)strlen(cmd)); ret = ts_console_exec(cmd, NULL); snprintf(result->output, sizeof(result->output), "LED filter stopped"); } @@ -979,7 +1132,7 @@ esp_err_t ts_action_exec_led(const ts_auto_action_led_t *led, } { const char *cmd = "led --stop-text --device matrix"; - ESP_LOGI(TAG, "Executing LED text stop CLI: %s", cmd); + ESP_LOGD(TAG, "Executing LED CLI (%u bytes)", (unsigned)strlen(cmd)); ret = ts_console_exec(cmd, NULL); snprintf(result->output, sizeof(result->output), "LED text stopped"); } @@ -1163,9 +1316,13 @@ esp_err_t ts_action_exec_device(const ts_auto_action_device_t *device, return ESP_OK; } -esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, - ts_action_result_t *result) -{ +static esp_err_t exec_ssh_ref_bound(const ts_auto_action_ssh_ref_t *, const action_binding_t *, + ts_action_result_t *); +esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ref, ts_action_result_t *result) { + return exec_ssh_ref_bound(ref, NULL, result); +} +static esp_err_t exec_ssh_ref_bound(const ts_auto_action_ssh_ref_t *ssh_ref, + const action_binding_t *binding, ts_action_result_t *result) { if (!ssh_ref || !result) { return ESP_ERR_INVALID_ARG; } @@ -1175,7 +1332,9 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, /* Look up the SSH command configuration */ ts_ssh_command_config_t cmd_config; - esp_err_t ret = ts_ssh_commands_config_get(ssh_ref->cmd_id, &cmd_config); + esp_err_t ret = binding ? ESP_OK : ts_ssh_commands_config_get(ssh_ref->cmd_id, &cmd_config); + if (binding) + cmd_config = binding->command; if (ret != ESP_OK) { snprintf(result->output, sizeof(result->output), "SSH command '%s' not found", ssh_ref->cmd_id); @@ -1190,22 +1349,24 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, result->status = TS_ACTION_STATUS_FAILED; return ESP_ERR_INVALID_STATE; } - - ESP_LOGI(TAG, "SSH ref [%s]: host=%s, cmd=%s", - ssh_ref->cmd_id, cmd_config.host_id, cmd_config.command); + + ESP_LOGI(TAG, "SSH ref [%s]: host=%s, command_bytes=%u", ssh_ref->cmd_id, cmd_config.host_id, + (unsigned)strlen(cmd_config.command)); ESP_LOGI(TAG, "SSH ref config: var_name='%s', nohup=%d, service_mode=%d, ready_pattern='%s'", cmd_config.var_name, cmd_config.nohup, cmd_config.service_mode, cmd_config.ready_pattern); /* Get SSH host config */ ts_action_ssh_host_t host; - if (ts_action_get_ssh_host(cmd_config.host_id, &host) != ESP_OK) { + if (binding) + host = binding->host; + if (!binding && ts_action_get_ssh_host(cmd_config.host_id, &host) != ESP_OK) { snprintf(result->output, sizeof(result->output), "SSH host '%s' not found for command '%s'", cmd_config.host_id, ssh_ref->cmd_id); result->status = TS_ACTION_STATUS_FAILED; return ESP_ERR_NOT_FOUND; } - + /* Expand variables in command * Use heap allocation to avoid stack overflow with large commands (up to 1024 bytes) */ @@ -1221,9 +1382,10 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, ts_action_expand_variables(cmd_config.command, expanded_cmd, TS_SSH_CMD_COMMAND_MAX); /* Handle nohup mode: wrap command for background execution */ - char *nohup_cmd = heap_caps_malloc(TS_SSH_CMD_COMMAND_MAX + 128, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + char *nohup_cmd = + heap_caps_malloc(TS_SSH_CMD_COMMAND_MAX * 5 + 1024, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (!nohup_cmd) { - nohup_cmd = malloc(TS_SSH_CMD_COMMAND_MAX + 128); + nohup_cmd = malloc(TS_SSH_CMD_COMMAND_MAX * 5 + 1024); } if (!nohup_cmd) { free(expanded_cmd); @@ -1232,47 +1394,30 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, return ESP_ERR_NO_MEM; } if (cmd_config.nohup) { - /* Generate safe name from command name for log/pid files - * Priority: cmd.name alphanumeric chars -> cmd_id alphanumeric chars -> "cmd" - * Pure Chinese names produce empty string, so fallback to cmd_id - */ - char safe_name[32] = {0}; - const char *src = cmd_config.name; - int j = 0; - for (int i = 0; src[i] && j < 20; i++) { - if ((src[i] >= 'a' && src[i] <= 'z') || - (src[i] >= 'A' && src[i] <= 'Z') || - (src[i] >= '0' && src[i] <= '9')) { - safe_name[j++] = src[i]; + if (cmd_config.service_mode) { + if (!ts_ssh_service_launch_command(&cmd_config, expanded_cmd, nohup_cmd, + TS_SSH_CMD_COMMAND_MAX * 5 + 1024)) { + free(expanded_cmd); + free(nohup_cmd); + result->status = TS_ACTION_STATUS_FAILED; + return ESP_ERR_INVALID_SIZE; } - } - if (j == 0) { - /* Fallback to cmd_id (e.g. "emb-pull-up" -> "embpullup") */ - const char *id_src = ssh_ref->cmd_id; - for (int i = 0; id_src[i] && j < 20; i++) { - if ((id_src[i] >= 'a' && id_src[i] <= 'z') || - (id_src[i] >= 'A' && id_src[i] <= 'Z') || - (id_src[i] >= '0' && id_src[i] <= '9')) { - safe_name[j++] = id_src[i]; - } + } else { + char safe_name[32]; + ts_ssh_service_safe_name(&cmd_config, safe_name); + int len = + snprintf(nohup_cmd, TS_SSH_CMD_COMMAND_MAX * 5 + 1024, + "nohup %s > /tmp/ts_nohup_%s.log 2>&1 & echo $! > /tmp/ts_nohup_%s.pid", + expanded_cmd, safe_name, safe_name); + if (len < 0 || len >= TS_SSH_CMD_COMMAND_MAX * 5 + 1024) { + free(expanded_cmd); + free(nohup_cmd); + result->status = TS_ACTION_STATUS_FAILED; + return ESP_ERR_INVALID_SIZE; } } - if (j == 0) { - strcpy(safe_name, "cmd"); - } - ESP_LOGI(TAG, "nohup safe_name='%s' (from name='%s', id='%s')", safe_name, cmd_config.name, ssh_ref->cmd_id); - - /* nohup command with PID file for process tracking - * Format: nohup > 2>&1 & echo $! > ; sleep 0.3; cat - * 注意:$! 可能获取中间 shell PID 而非真实进程 PID(差 1), - * 前端已通过 PID-1 fallback 处理此情况 - */ - snprintf(nohup_cmd, TS_SSH_CMD_COMMAND_MAX + 128, - "nohup %s > /tmp/ts_nohup_%s.log 2>&1 & echo $! > /tmp/ts_nohup_%s.pid; sleep 0.3; cat /tmp/ts_nohup_%s.pid", - expanded_cmd, safe_name, safe_name, safe_name); - ESP_LOGI(TAG, "SSH nohup mode: %s", nohup_cmd); } - + /* Create SSH session */ ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); config.host = host.host; @@ -1283,7 +1428,7 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, /* Load SSH key from keystore if using key auth */ char *key_data = NULL; size_t key_len = 0; - + char full_path[128] = {0}; if (host.use_key_auth && host.key_path[0]) { /* host.key_path actually contains the keyid */ const char *keyid = host.key_path; @@ -1298,7 +1443,6 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, ESP_LOGI(TAG, "Loaded SSH key '%s' from keystore (%zu bytes)", keyid, key_len); } else { /* Fallback: try as file path */ - char full_path[128]; if (keyid[0] == '/') { strncpy(full_path, keyid, sizeof(full_path) - 1); } else { @@ -1337,13 +1481,34 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, if (key_data) free(key_data); return ret; } - + + uint32_t run_generation = 0; + if (cmd_config.nohup && cmd_config.service_mode) { + ret = ts_ssh_service_begin(&cmd_config, session, &run_generation); + if (ret != ESP_OK) { + result->status = TS_ACTION_STATUS_FAILED; + snprintf(result->output, sizeof(result->output), + "Service busy or remote state unknown; verify before retry"); + ts_ssh_session_destroy(session); + free(expanded_cmd); + free(nohup_cmd); + free(key_data); + return ret; + } + } /* Execute command */ ts_ssh_exec_result_t exec_result = {0}; const char *cmd_to_exec = cmd_config.nohup ? nohup_cmd : expanded_cmd; - ESP_LOGI(TAG, "SSH exec command: [%s]", cmd_to_exec); + ESP_LOGD(TAG, "SSH execution: command=%s, bytes=%u", ssh_ref->cmd_id, + (unsigned)strlen(cmd_to_exec)); ret = ts_ssh_exec(session, cmd_to_exec, &exec_result); - + if (run_generation) { + bool launched = ts_ssh_service_finish(cmd_config.id, run_generation, + ret == ESP_OK && exec_result.exit_code == 0 ? exec_result.stdout_data : NULL, session); + if (!launched && ret == ESP_OK) + ret = ESP_ERR_INVALID_RESPONSE; + } + if (ret == ESP_OK) { result->exit_code = exec_result.exit_code; if (exec_result.stdout_data && exec_result.stdout_len > 0) { @@ -1365,7 +1530,7 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, : TS_ACTION_STATUS_FAILED; /* Update variables if var_name is configured */ - if (cmd_config.var_name[0]) { + if (cmd_config.var_name[0] && !run_generation) { char var_full[64]; /* Set exit_code variable */ @@ -1388,42 +1553,19 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, cmd_config.nohup, cmd_config.service_mode, cmd_config.ready_pattern); ts_variable_set_string(var_full, debug_info); } - + /* Handle service mode: start log watching for nohup commands */ - if (cmd_config.nohup && cmd_config.service_mode && + if (exec_result.exit_code == 0 && cmd_config.nohup && cmd_config.service_mode && cmd_config.ready_pattern[0] && cmd_config.var_name[0]) { - - /* Generate safe name (same logic as nohup wrapper above) - * Priority: cmd.name -> cmd_id -> "cmd" - */ - char safe_name[32] = {0}; - const char *src = cmd_config.name; - int j = 0; - for (int i = 0; src[i] && j < 20; i++) { - if ((src[i] >= 'a' && src[i] <= 'z') || - (src[i] >= 'A' && src[i] <= 'Z') || - (src[i] >= '0' && src[i] <= '9')) { - safe_name[j++] = src[i]; - } - } - if (j == 0) { - const char *id_src = ssh_ref->cmd_id; - for (int i = 0; id_src[i] && j < 20; i++) { - if ((id_src[i] >= 'a' && id_src[i] <= 'z') || - (id_src[i] >= 'A' && id_src[i] <= 'Z') || - (id_src[i] >= '0' && id_src[i] <= '9')) { - safe_name[j++] = id_src[i]; - } - } - } - if (j == 0) { - strcpy(safe_name, "cmd"); - } - + + char safe_name[32]; + ts_ssh_service_safe_name(&cmd_config, safe_name); ts_ssh_log_watch_config_t watch_config = { .timeout_sec = cmd_config.ready_timeout_sec > 0 ? cmd_config.ready_timeout_sec : 60, .check_interval_ms = cmd_config.ready_check_interval_ms > 0 ? cmd_config.ready_check_interval_ms : 3000 }; + watch_config.run_generation = run_generation; + strcpy(watch_config.command_id, cmd_config.id); strncpy(watch_config.host_id, cmd_config.host_id, sizeof(watch_config.host_id) - 1); snprintf(watch_config.log_file, sizeof(watch_config.log_file), "/tmp/ts_nohup_%s.log", safe_name); @@ -1432,6 +1574,9 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, strncpy(watch_config.var_name, cmd_config.var_name, sizeof(watch_config.var_name) - 1); esp_err_t watch_ret = ts_ssh_log_watch_start(&watch_config, NULL); + if (watch_ret != ESP_OK) + ts_ssh_service_observe(cmd_config.id, run_generation, "unknown", + cmd_config.var_name); if (watch_ret == ESP_OK) { ESP_LOGI(TAG, "🔍 Service mode: watching log for '%s' (fail='%s', timeout: %us)", cmd_config.ready_pattern, cmd_config.service_fail_pattern, watch_config.timeout_sec); @@ -1439,10 +1584,9 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, ESP_LOGW(TAG, "Failed to start log watch: %s", esp_err_to_name(watch_ret)); } } - + /* Free result strings */ - if (exec_result.stdout_data) free(exec_result.stdout_data); - if (exec_result.stderr_data) free(exec_result.stderr_data); + ts_ssh_exec_result_free(&exec_result); } else { snprintf(result->output, sizeof(result->output), "SSH exec failed: %s", esp_err_to_name(ret)); @@ -1450,7 +1594,8 @@ esp_err_t ts_action_exec_ssh_ref(const ts_auto_action_ssh_ref_t *ssh_ref, ? TS_ACTION_STATUS_TIMEOUT : TS_ACTION_STATUS_FAILED; } - + + ts_ssh_exec_result_free(&exec_result); /* Cleanup */ ts_ssh_disconnect(session); ts_ssh_session_destroy(session); @@ -1501,9 +1646,9 @@ esp_err_t ts_action_exec_cli(const ts_auto_action_cli_t *cli, result->status = TS_ACTION_STATUS_FAILED; return ESP_ERR_INVALID_ARG; } - - ESP_LOGI(TAG, "Executing CLI command: %s", cli->command); - + + ESP_LOGD(TAG, "Executing CLI command (%u bytes)", (unsigned)strlen(cli->command)); + /* Execute CLI command using ts_console_exec */ ts_cmd_result_t cmd_result = {0}; esp_err_t ret = ts_console_exec(cli->command, &cmd_result); @@ -1553,10 +1698,9 @@ esp_err_t ts_action_exec_cli(const ts_auto_action_cli_t *cli, if (cmd_result.data) { free(cmd_result.data); } - - ESP_LOGD(TAG, "CLI result: cmd=%s, exit=%d, duration=%lu ms", - cli->command, result->exit_code, result->duration_ms); - + + ESP_LOGD(TAG, "CLI result: exit=%d, duration=%lu ms", result->exit_code, result->duration_ms); + return ret; } @@ -1572,8 +1716,8 @@ static esp_err_t execute_action_internal(const ts_auto_action_t *action, return ts_action_exec_ssh(&action->ssh, result); case TS_AUTO_ACT_SSH_CMD_REF: - return ts_action_exec_ssh_ref(&action->ssh_ref, result); - + return exec_ssh_ref_bound(&action->ssh_ref, action->runtime_binding, result); + case TS_AUTO_ACT_CLI: return ts_action_exec_cli(&action->cli, result); @@ -1618,18 +1762,32 @@ static void action_executor_task(void *arg) while (s_ctx->running) { if (xQueueReceive(s_ctx->action_queue, &entry, pdMS_TO_TICKS(1000)) == pdTRUE) { - if (!s_ctx->running) break; - + if (!s_ctx->running) { + ts_action_snapshot_release(&entry.action); + if (entry.result_ptr) + entry.result_ptr->status = TS_ACTION_STATUS_CANCELLED; + if (entry.done_sem) + xSemaphoreGive(entry.done_sem); + completion_release(entry.completion); + action_finished(); + break; + } + ts_action_result_t local_result = {0}; ts_action_result_t *result = entry.result_ptr ? entry.result_ptr : &local_result; /* Handle delay */ - if (entry.action.delay_ms > 0) { - vTaskDelay(pdMS_TO_TICKS(entry.action.delay_ms)); + uint32_t delay = entry.action.delay_ms; + while (delay && s_ctx->accepting) { + uint32_t slice = delay > 100 ? 100 : delay; + vTaskDelay(pdMS_TO_TICKS(slice)); + delay -= slice; } - - /* Execute action (safe: this task has DRAM stack) */ - execute_action_internal(&entry.action, result); + /* Stop discards work not yet started; active I/O owns its cleanup. */ + if (s_ctx->accepting) + execute_action_internal(&entry.action, result); + else + result->status = TS_ACTION_STATUS_CANCELLED; /* Callback (async mode) */ if (entry.callback) { @@ -1637,10 +1795,7 @@ static void action_executor_task(void *arg) } /* Signal completion (sync mode) */ - if (entry.done_sem) { - xSemaphoreGive(entry.done_sem); - } - + /* Update stats */ xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); s_ctx->stats.total_executed++; @@ -1652,11 +1807,18 @@ static void action_executor_task(void *arg) s_ctx->stats.total_failed++; } xSemaphoreGive(s_ctx->stats_mutex); + ts_action_snapshot_release(&entry.action); + if (entry.done_sem) + xSemaphoreGive(entry.done_sem); + completion_release(entry.completion); + action_finished(); } } ESP_LOGI(TAG, "Action executor task exiting"); + xSemaphoreTake(s_ctx->stats_mutex, portMAX_DELAY); s_ctx->executor_task = NULL; + xSemaphoreGive(s_ctx->stats_mutex); vTaskDelete(NULL); } @@ -1914,8 +2076,7 @@ esp_err_t ts_action_template_add(const ts_action_template_t *tpl) return ESP_OK; } -esp_err_t ts_action_template_remove(const char *id) -{ +static esp_err_t template_remove_impl(const char *id) { if (!s_ctx || !id || !id[0]) { return ESP_ERR_INVALID_ARG; } @@ -2056,8 +2217,7 @@ esp_err_t ts_action_template_execute(const char *id, ts_action_result_t *result) return ret; } -esp_err_t ts_action_template_update(const char *id, const ts_action_template_t *tpl) -{ +static esp_err_t template_update_impl(const char *id, const ts_action_template_t *tpl) { if (!s_ctx || !id || !tpl) { return ESP_ERR_INVALID_ARG; } @@ -2946,3 +3106,34 @@ esp_err_t ts_action_templates_load_from_file(const char *filepath) return ESP_OK; } + +static bool template_binding_protected(const char *id, const ts_action_template_t *next) { + ts_action_template_t *old = heap_caps_malloc(sizeof(*old), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!old) + return true; + bool busy = false; + if (ts_action_template_get(id, old) == ESP_OK && old->action.type == TS_AUTO_ACT_SSH_CMD_REF && + (!next || next->action.type != old->action.type || + strcmp(next->action.ssh_ref.cmd_id, old->action.ssh_ref.cmd_id))) + busy = ts_ssh_service_command_protected(old->action.ssh_ref.cmd_id); + free(old); + return busy; +} +esp_err_t ts_action_template_update(const char *id, const ts_action_template_t *next) { + if (!id || !next) + return ESP_ERR_INVALID_ARG; + ts_ssh_binding_lock(); + esp_err_t ret = template_binding_protected(id, next) ? ESP_ERR_INVALID_STATE + : template_update_impl(id, next); + ts_ssh_binding_unlock(); + return ret; +} +esp_err_t ts_action_template_remove(const char *id) { + if (!id) + return ESP_ERR_INVALID_ARG; + ts_ssh_binding_lock(); + esp_err_t ret = + template_binding_protected(id, NULL) ? ESP_ERR_INVALID_STATE : template_remove_impl(id); + ts_ssh_binding_unlock(); + return ret; +} diff --git a/components/ts_automation/src/ts_automation.c b/components/ts_automation/src/ts_automation.c index 377db2e..c700e27 100644 --- a/components/ts_automation/src/ts_automation.c +++ b/components/ts_automation/src/ts_automation.c @@ -26,6 +26,7 @@ #include "freertos/semphr.h" #include "cJSON.h" +#include #include #include @@ -40,6 +41,7 @@ static const char *TAG = "ts_automation"; */ typedef struct { ts_automation_state_t state; // 当前状态 + atomic_bool stopping; TaskHandle_t task_handle; // 主任务句柄 SemaphoreHandle_t mutex; // 状态互斥锁 @@ -198,11 +200,12 @@ esp_err_t ts_automation_deinit(void) ESP_LOGI(TAG, "Deinitializing automation engine"); // 先停止 - ts_automation_stop(); - - // 反初始化子模块 - ts_action_manager_deinit(); - ts_rule_engine_deinit(); + esp_err_t ret = ts_automation_stop(); + if (ret != ESP_OK) return ret; + ret = ts_action_manager_deinit(); + if (ret != ESP_OK) return ret; + ret = ts_rule_engine_deinit(); + if (ret != ESP_OK) return ret; ts_source_manager_deinit(); ts_variable_deinit(); @@ -227,86 +230,52 @@ bool ts_automation_is_initialized(void) /* 控制接口 */ /*===========================================================================*/ -esp_err_t ts_automation_start(void) -{ - if (s_ctx.state == TS_AUTO_STATE_UNINITIALIZED) { - ESP_LOGE(TAG, "Not initialized"); - return ESP_ERR_INVALID_STATE; - } - - if (s_ctx.state == TS_AUTO_STATE_RUNNING) { - ESP_LOGW(TAG, "Already running"); - return ESP_OK; - } - - ESP_LOGI(TAG, "Starting automation engine"); - - // 启动数据源 - esp_err_t ret = ts_source_start_all(); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Some sources failed to start"); - } - - // 创建主任务 - BaseType_t xret = xTaskCreatePinnedToCore( - automation_task, - "ts_auto", - CONFIG_TS_AUTOMATION_TASK_STACK_SIZE, - NULL, - CONFIG_TS_AUTOMATION_TASK_PRIORITY, - &s_ctx.task_handle, - 1 // CPU 1 - ); - - if (xret != pdPASS) { - ESP_LOGE(TAG, "Failed to create task"); - return ESP_ERR_NO_MEM; - } - +esp_err_t ts_automation_start(void) { + if (!s_ctx.mutex) return ESP_ERR_INVALID_STATE; xSemaphoreTake(s_ctx.mutex, portMAX_DELAY); + if (s_ctx.stopping) { xSemaphoreGive(s_ctx.mutex); return ESP_ERR_INVALID_STATE; } + if (s_ctx.state == TS_AUTO_STATE_RUNNING) { xSemaphoreGive(s_ctx.mutex); return ESP_OK; } + if (s_ctx.task_handle || ts_action_manager_resume() != ESP_OK) { + xSemaphoreGive(s_ctx.mutex); return ESP_ERR_INVALID_STATE; + } + ts_source_start_all(); s_ctx.state = TS_AUTO_STATE_RUNNING; + BaseType_t ret = xTaskCreatePinnedToCore(automation_task, "ts_auto", + CONFIG_TS_AUTOMATION_TASK_STACK_SIZE, NULL, CONFIG_TS_AUTOMATION_TASK_PRIORITY, + &s_ctx.task_handle, 1); + if (ret != pdPASS) s_ctx.state = TS_AUTO_STATE_INITIALIZED; xSemaphoreGive(s_ctx.mutex); - - ESP_LOGI(TAG, "Automation engine started"); - return ESP_OK; + return ret == pdPASS ? ESP_OK : ESP_ERR_NO_MEM; } - -esp_err_t ts_automation_stop(void) -{ - if (s_ctx.state != TS_AUTO_STATE_RUNNING && - s_ctx.state != TS_AUTO_STATE_PAUSED) { - return ESP_OK; - } - - ESP_LOGI(TAG, "Stopping automation engine"); - - // 设置停止状态 +esp_err_t ts_automation_stop(void) { + if (!s_ctx.mutex) return ESP_OK; xSemaphoreTake(s_ctx.mutex, portMAX_DELAY); - s_ctx.state = TS_AUTO_STATE_INITIALIZED; + s_ctx.stopping = true; xSemaphoreGive(s_ctx.mutex); - - // 等待任务退出 - if (s_ctx.task_handle) { - // 给任务一些时间自行退出 - vTaskDelay(pdMS_TO_TICKS(100)); - - // 如果还在运行,强制删除 - if (eTaskGetState(s_ctx.task_handle) != eDeleted) { - vTaskDelete(s_ctx.task_handle); - } - s_ctx.task_handle = NULL; + /* No external vTaskDelete: evaluator returns through rule lease cleanup. + * Async actions may outlive it; do not reopen admission until both are idle. */ + bool exited = false; + esp_err_t idle = ESP_ERR_TIMEOUT; + for (unsigned waited = 0; waited <= 200; waited += 10) { + idle = ts_action_manager_quiesce(); + xSemaphoreTake(s_ctx.mutex, portMAX_DELAY); + exited = s_ctx.task_handle == NULL; + xSemaphoreGive(s_ctx.mutex); + if (exited && idle == ESP_OK) break; + if (waited < 200) vTaskDelay(pdMS_TO_TICKS(10)); } - - // 停止数据源 + if (!exited || idle != ESP_OK) return ESP_ERR_TIMEOUT; + xSemaphoreTake(s_ctx.mutex, portMAX_DELAY); ts_source_stop_all(); - - ESP_LOGI(TAG, "Automation engine stopped"); + s_ctx.state = TS_AUTO_STATE_INITIALIZED; + s_ctx.stopping = false; + xSemaphoreGive(s_ctx.mutex); return ESP_OK; } esp_err_t ts_automation_pause(void) { - if (s_ctx.state != TS_AUTO_STATE_RUNNING) { + if (s_ctx.stopping || s_ctx.state != TS_AUTO_STATE_RUNNING) { return ESP_ERR_INVALID_STATE; } @@ -320,7 +289,7 @@ esp_err_t ts_automation_pause(void) esp_err_t ts_automation_resume(void) { - if (s_ctx.state != TS_AUTO_STATE_PAUSED) { + if (s_ctx.stopping || s_ctx.state != TS_AUTO_STATE_PAUSED) { return ESP_ERR_INVALID_STATE; } @@ -390,9 +359,10 @@ static void automation_task(void *arg) // 检查状态 xSemaphoreTake(s_ctx.mutex, portMAX_DELAY); ts_automation_state_t state = s_ctx.state; + bool stopping = s_ctx.stopping; xSemaphoreGive(s_ctx.mutex); - if (state != TS_AUTO_STATE_RUNNING && state != TS_AUTO_STATE_PAUSED) { + if (stopping || (state != TS_AUTO_STATE_RUNNING && state != TS_AUTO_STATE_PAUSED)) { break; // 退出任务 } @@ -418,7 +388,9 @@ static void automation_task(void *arg) } ESP_LOGI(TAG, "Automation task exiting"); + xSemaphoreTake(s_ctx.mutex, portMAX_DELAY); s_ctx.task_handle = NULL; + xSemaphoreGive(s_ctx.mutex); vTaskDelete(NULL); } diff --git a/components/ts_automation/src/ts_rule_codec.c b/components/ts_automation/src/ts_rule_codec.c new file mode 100644 index 0000000..68ca25f --- /dev/null +++ b/components/ts_automation/src/ts_rule_codec.c @@ -0,0 +1,502 @@ +#include "ts_rule_codec.h" +#include "esp_heap_caps.h" +#include "ts_action_manager.h" +#include +#include +#include +#include +#include +/* Descriptors cover the actual C fields, not raw struct bytes or padding. */ +typedef enum { STRING, BOOL, U8, U16, U32, I16, ENUM } field_type; +typedef struct { + const char *name; + size_t offset, size; + field_type type; + int max; +} field; +#define F(T, m, k, t, lim) {k, offsetof(T, m), sizeof(((T *)0)->m), t, lim} +#define A(m, k, t, lim) F(ts_auto_action_t, m, k, t, lim) +#define R(m, k, t, lim) F(ts_auto_rule_t, m, k, t, lim) +static const field common[] = {A(delay_ms, "delay_ms", U16, 65535), A(async, "async", BOOL, 1), + A(repeat_count, "repeat_count", U8, 255), + A(repeat_interval_ms, "repeat_interval_ms", U16, 65535), + A(template_id, "template_id", STRING, 0)}; +static const field rule_fields[] = {R(id, "id", STRING, 0), + R(name, "name", STRING, 0), + R(icon, "icon", STRING, 0), + R(enabled, "enabled", BOOL, 1), + R(manual_trigger, "manual_trigger", BOOL, 1), + R(show_on_dashboard, "show_on_dashboard", BOOL, 1), + R(allow_manual_trigger, "allow_manual_trigger", BOOL, 1), + R(cooldown_ms, "cooldown_ms", U32, 0), + R(revision, "revision", U32, 0)}; +static const field led_fields[] = { + A(led.device, "device", STRING, 0), + A(led.ctrl_type, "ctrl_type", ENUM, 9), + A(led.index, "index", U8, 255), + A(led.r, "r", U8, 255), + A(led.g, "g", U8, 255), + A(led.b, "b", U8, 255), + A(led.brightness, "brightness", U8, 255), + A(led.effect, "effect", STRING, 0), + A(led.duration_ms, "duration_ms", U16, 65535), + A(led.speed, "speed", U8, 255), + A(led.text, "text", STRING, 0), + A(led.font, "font", STRING, 0), + A(led.image_path, "image_path", STRING, 0), + A(led.qr_text, "qr_text", STRING, 0), + A(led.qr_ecc, "qr_ecc", U8, 255), + A(led.filter, "filter", STRING, 0), + A(led.center, "center", BOOL, 1), + A(led.loop, "loop", BOOL, 1), + A(led.scroll, "scroll", STRING, 0), + A(led.align, "align", STRING, 0), + A(led.x, "x", I16, 32767), + A(led.y, "y", I16, 32767), +}; +static const field ssh_fields[] = { + A(ssh.host_ref, "host_ref", STRING, 0), + A(ssh.command, "command", STRING, 0), + A(ssh.async, "ssh_async", BOOL, 1), + A(ssh.timeout_ms, "timeout_ms", U32, 0), +}; +static const field gpio_fields[] = { + A(gpio.pin, "pin", U8, 255), + A(gpio.level, "level", BOOL, 1), + A(gpio.pulse_ms, "pulse_ms", U32, 0), +}; +static const field webhook_fields[] = { + A(webhook.url, "url", STRING, 0), + A(webhook.method, "method", STRING, 0), + A(webhook.body_template, "body_template", STRING, 0), +}; +static const field log_fields[] = { + A(log.level, "level", U8, 255), + A(log.message, "message", STRING, 0), +}; +static const field set_var_fields[] = { + A(set_var.variable, "variable", STRING, 0), +}; +static const field device_fields[] = { + A(device.device, "device", STRING, 0), + A(device.action, "action", STRING, 0), +}; +static const field ssh_ref_fields[] = { + A(ssh_ref.cmd_id, "cmd_id", STRING, 0), +}; +static const field cli_fields[] = { + A(cli.command, "command", STRING, 0), + A(cli.var_name, "var_name", STRING, 0), + A(cli.timeout_ms, "timeout_ms", U32, 0), +}; +static const struct { + const field *fields; + size_t count; +} by_type[] = { + {led_fields, sizeof(led_fields) / sizeof(field)}, + {ssh_fields, sizeof(ssh_fields) / sizeof(field)}, + {gpio_fields, sizeof(gpio_fields) / sizeof(field)}, + {webhook_fields, sizeof(webhook_fields) / sizeof(field)}, + {log_fields, sizeof(log_fields) / sizeof(field)}, + {set_var_fields, sizeof(set_var_fields) / sizeof(field)}, + {device_fields, sizeof(device_fields) / sizeof(field)}, + {ssh_ref_fields, sizeof(ssh_ref_fields) / sizeof(field)}, + {cli_fields, sizeof(cli_fields) / sizeof(field)}, +}; +static const char *types[] = {"led", "ssh", "gpio", "webhook", "log", + "set_var", "device_ctrl", "ssh_cmd_ref", "cli"}; +static const char *ops[] = {"eq", "ne", "lt", "le", "gt", "ge", "contains"}; +static const char *repeats[] = {"once", "while_true", "count"}; +static int choice(const cJSON *j, const char *const *names, size_t count, int def) { + if (!j) + return def; + if (!cJSON_IsString(j)) + return -1; + for (size_t i = 0; i < count; ++i) + if (!strcmp(j->valuestring, names[i])) + return i; + return -1; +} +static bool fields_read(const cJSON *j, void *value, const field *fields, size_t count) { + for (size_t i = 0; i < count; ++i) { + const field *f = &fields[i]; + const cJSON *v = cJSON_GetObjectItemCaseSensitive(j, f->name); + if (!v) + continue; + char *p = (char *)value + f->offset; + if (f->type == STRING) { + if (!cJSON_IsString(v) || strlen(v->valuestring) >= f->size) + return false; + strcpy(p, v->valuestring); + continue; + } + if (f->type == BOOL) { + if (!cJSON_IsBool(v)) + return false; + *(bool *)p = cJSON_IsTrue(v); + continue; + } + double d = v->valuedouble; + double max = f->type == U32 ? UINT32_MAX : f->max; + if (!cJSON_IsNumber(v) || !isfinite(d) || trunc(d) != d || d > (double)max || + d < (f->type == I16 ? INT16_MIN : 0)) + return false; + switch (f->type) { + case U8: + *(uint8_t *)p = d; + break; + case U16: + *(uint16_t *)p = d; + break; + case U32: + *(uint32_t *)p = d; + break; + case I16: + *(int16_t *)p = d; + break; + case ENUM: + *(int *)p = d; + break; + default: + return false; + } + } + return true; +} +static bool fields_write(cJSON *j, const void *value, const field *fields, size_t count) { + for (size_t i = 0; i < count; ++i) { + const field *f = &fields[i]; + const char *p = (const char *)value + f->offset; + cJSON *v = NULL; + if (f->type == STRING) { + if (!memchr(p, 0, f->size)) + return false; + v = cJSON_CreateString(p); + } else if (f->type == BOOL) + v = cJSON_CreateBool(*(const bool *)p); + else { + double d = 0; + switch (f->type) { + case U8: + d = *(const uint8_t *)p; + break; + case U16: + d = *(const uint16_t *)p; + break; + case U32: + d = *(const uint32_t *)p; + break; + case I16: + d = *(const int16_t *)p; + break; + case ENUM: + d = *(const int *)p; + break; + default: + return false; + } + v = cJSON_CreateNumber(d); + } + if (!v) + return false; + if (!cJSON_AddItemToObject(j, f->name, v)) { + cJSON_Delete(v); + return false; + } + } + return true; +} +static bool value_read(const cJSON *j, ts_auto_value_t *v) { + if (!j || cJSON_IsNull(j)) { + v->type = TS_AUTO_VAL_NULL; + return true; + } + if (cJSON_IsBool(j)) { + v->type = TS_AUTO_VAL_BOOL; + v->bool_val = cJSON_IsTrue(j); + return true; + } + if (cJSON_IsNumber(j) && isfinite(j->valuedouble)) { + double d = j->valuedouble; + if (d >= INT32_MIN && d <= INT32_MAX && trunc(d) == d) { + v->type = TS_AUTO_VAL_INT; + v->int_val = d; + } else { + v->type = TS_AUTO_VAL_FLOAT; + v->float_val = d; + } + return true; + } + if (cJSON_IsString(j) && strlen(j->valuestring) < sizeof(v->str_val)) { + v->type = TS_AUTO_VAL_STRING; + strcpy(v->str_val, j->valuestring); + return true; + } + return false; +} +static bool typed_value_read(const cJSON *object, ts_auto_value_t *v) { + const cJSON *value = cJSON_GetObjectItemCaseSensitive(object, "value"); + if (!value_read(value, v)) + return false; + const cJSON *type = cJSON_GetObjectItemCaseSensitive(object, "value_type"); + if (!type) + return true; + if (!cJSON_IsNumber(type) || type->valuedouble != type->valueint) + return false; + if (type->valueint == TS_AUTO_VAL_FLOAT && cJSON_IsNumber(value)) { + memset(v, 0, sizeof(*v)); + v->type = TS_AUTO_VAL_FLOAT; + v->float_val = value->valuedouble; + return true; + } + return type->valueint == v->type; +} +static cJSON *value_write(const ts_auto_value_t *v) { + switch (v->type) { + case TS_AUTO_VAL_NULL: + return cJSON_CreateNull(); + case TS_AUTO_VAL_BOOL: + return cJSON_CreateBool(v->bool_val); + case TS_AUTO_VAL_INT: + return cJSON_CreateNumber(v->int_val); + case TS_AUTO_VAL_FLOAT: + return isfinite(v->float_val) ? cJSON_CreateNumber(v->float_val) : NULL; + case TS_AUTO_VAL_STRING: + return memchr(v->str_val, 0, sizeof(v->str_val)) ? cJSON_CreateString(v->str_val) : NULL; + default: + return NULL; + } +} +static bool condition_read(const cJSON *j, char *variable, int *op, ts_auto_value_t *v) { + const cJSON *name = cJSON_GetObjectItemCaseSensitive(j, "variable"); + int o = choice(cJSON_GetObjectItemCaseSensitive(j, "operator"), ops, 7, 0); + if (!cJSON_IsObject(j) || !cJSON_IsString(name) || !name->valuestring[0] || + strlen(name->valuestring) >= TS_AUTO_NAME_MAX_LEN || o < 0) + return false; + strcpy(variable, name->valuestring); + *op = o; + return typed_value_read(j, v); +} +static cJSON *condition_write(const char *variable, int op, const ts_auto_value_t *value) { + if (op < 0 || op >= 7) + return NULL; + cJSON *j = cJSON_CreateObject(), *v = value_write(value); + if (!j || !v) { + cJSON_Delete(j); + cJSON_Delete(v); + return NULL; + } + if (!cJSON_AddItemToObject(j, "value", v)) { + cJSON_Delete(v); + cJSON_Delete(j); + return NULL; + } + if (!cJSON_AddStringToObject(j, "variable", variable) || + !cJSON_AddStringToObject(j, "operator", ops[op]) || + !cJSON_AddNumberToObject(j, "value_type", value->type)) { + cJSON_Delete(j); + return NULL; + } + return j; +} +bool ts_rule_id_valid(const char *id) { + if (!id || !id[0] || strlen(id) >= TS_AUTO_NAME_MAX_LEN || !strcmp(id, ".") || + !strcmp(id, "..")) + return false; + for (const unsigned char *p = (const unsigned char *)id; *p; ++p) + if (*p < 32 || *p == '/' || *p == '\\') + return false; + return true; +} +void ts_rule_dispose(ts_auto_rule_t *r) { + if (!r) + return; + free(r->conditions.conditions); + free(r->actions); + memset(r, 0, sizeof(*r)); +} +esp_err_t ts_rule_decode(const cJSON *j, ts_auto_rule_t *r) { + if (!r || !cJSON_IsObject(j)) + return ESP_ERR_INVALID_ARG; + memset(r, 0, sizeof(*r)); + r->enabled = true; + r->revision = 1; + if (!fields_read(j, r, rule_fields, sizeof(rule_fields) / sizeof(field)) || + !ts_rule_id_valid(r->id) || !r->name[0]) + goto invalid; + if (cJSON_HasObjectItem(j, "show_on_dashboard")) + r->presentation_fields |= 1; + if (cJSON_HasObjectItem(j, "allow_manual_trigger")) + r->presentation_fields |= 2; + const cJSON *c = cJSON_GetObjectItemCaseSensitive(j, "conditions"), *items = c; + const cJSON *logic = cJSON_GetObjectItemCaseSensitive(j, "logic"); + if (cJSON_IsObject(c)) { + items = cJSON_GetObjectItemCaseSensitive(c, "items"); + logic = cJSON_GetObjectItemCaseSensitive(c, "logic"); + } + const char *logics[] = {"and", "or"}; + int li = choice(logic, logics, 2, 0); + if (li < 0) + goto invalid; + r->conditions.logic = li; + if (items) { + if (!cJSON_IsArray(items) || cJSON_GetArraySize(items) > UINT8_MAX) + goto invalid; + r->conditions.count = cJSON_GetArraySize(items); + } + if (r->conditions.count) { + r->conditions.conditions = heap_caps_calloc( + r->conditions.count, sizeof(ts_auto_condition_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!r->conditions.conditions) + goto oom; + } + for (unsigned i = 0; i < r->conditions.count; ++i) { + ts_auto_condition_t *cond = &r->conditions.conditions[i]; + int op; + if (!condition_read(cJSON_GetArrayItem(items, i), cond->variable, &op, &cond->value)) + goto invalid; + cond->op = op; + } + const cJSON *actions = cJSON_GetObjectItemCaseSensitive(j, "actions"); + if (!cJSON_IsArray(actions) || cJSON_GetArraySize(actions) > UINT8_MAX || + !cJSON_GetArraySize(actions)) + goto invalid; + r->action_count = cJSON_GetArraySize(actions); + r->actions = heap_caps_calloc(r->action_count, sizeof(ts_auto_action_t), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!r->actions) + goto oom; + for (unsigned i = 0; i < r->action_count; ++i) { + const cJSON *a = cJSON_GetArrayItem(actions, i); + ts_auto_action_t *out = &r->actions[i]; + if (!cJSON_IsObject(a)) + goto invalid; + const cJSON *type = cJSON_GetObjectItemCaseSensitive(a, "type"), + *tpl = cJSON_GetObjectItemCaseSensitive(a, "template_id"); + if (!type && cJSON_IsString(tpl)) { + ts_action_template_t *t = + heap_caps_calloc(1, sizeof(*t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!t) + goto oom; + esp_err_t ret = ts_action_template_get(tpl->valuestring, t); + if (ret == ESP_OK) + *out = t->action; + free(t); + if (ret != ESP_OK) + out->type = TS_AUTO_ACT_TEMPLATE_REF; + } else { + int ty = choice(type, types, 9, -1); + if (cJSON_IsString(type) && !strcmp(type->valuestring, "device")) + ty = TS_AUTO_ACT_DEVICE_CTRL; + if (ty < 0) + goto invalid; + out->type = ty; + } + if (!fields_read(a, out, common, sizeof(common) / sizeof(field)) || + (out->type != TS_AUTO_ACT_TEMPLATE_REF && + !fields_read(a, out, by_type[out->type].fields, by_type[out->type].count))) + goto invalid; + int rep = choice(cJSON_GetObjectItemCaseSensitive(a, "repeat_mode"), repeats, 3, + out->repeat_mode); + if (rep < 0) + goto invalid; + out->repeat_mode = rep; + if (cJSON_HasObjectItem(a, "condition")) { + const cJSON *ac = cJSON_GetObjectItemCaseSensitive(a, "condition"); + out->condition.has_condition = !cJSON_IsNull(ac); + int op; + if (out->condition.has_condition) { + if (!condition_read(ac, out->condition.variable, &op, &out->condition.value)) + goto invalid; + out->condition.op = op; + } + } + if (out->type == TS_AUTO_ACT_SET_VAR && !typed_value_read(a, &out->set_var.value)) + goto invalid; + } + return ESP_OK; +oom: + ts_rule_dispose(r); + return ESP_ERR_NO_MEM; +invalid: + ts_rule_dispose(r); + return ESP_ERR_INVALID_ARG; +} +cJSON *ts_rule_encode(const ts_auto_rule_t *r) { + if (!r || (r->conditions.count && !r->conditions.conditions) || + (r->action_count && !r->actions) || + (r->conditions.logic != TS_AUTO_LOGIC_AND && r->conditions.logic != TS_AUTO_LOGIC_OR)) + return NULL; + cJSON *j = cJSON_CreateObject(); + if (!j) + return NULL; + if (!fields_write(j, r, rule_fields, sizeof(rule_fields) / sizeof(field))) + goto fail; + if (!(r->presentation_fields & 1)) + cJSON_DeleteItemFromObject(j, "show_on_dashboard"); + if (!(r->presentation_fields & 2)) + cJSON_DeleteItemFromObject(j, "allow_manual_trigger"); + if (!cJSON_AddStringToObject(j, "logic", + r->conditions.logic == TS_AUTO_LOGIC_OR ? "or" : "and")) + goto fail; + cJSON *conditions = cJSON_AddArrayToObject(j, "conditions"), + *actions = cJSON_AddArrayToObject(j, "actions"); + if (!conditions || !actions) + goto fail; + for (unsigned i = 0; i < r->conditions.count; ++i) { + const ts_auto_condition_t *c = &r->conditions.conditions[i]; + cJSON *cj = condition_write(c->variable, c->op, &c->value); + if (!cj) + goto fail; + if (!cJSON_AddItemToArray(conditions, cj)) { + cJSON_Delete(cj); + goto fail; + } + } + for (unsigned i = 0; i < r->action_count; ++i) { + const ts_auto_action_t *a = &r->actions[i]; + if ((a->type == TS_AUTO_ACT_TEMPLATE_REF && !a->template_id[0]) || a->type < 0 || + a->type > TS_AUTO_ACT_TEMPLATE_REF || a->repeat_mode < 0 || + a->repeat_mode > TS_AUTO_REPEAT_COUNT) + goto fail; + cJSON *aj = cJSON_CreateObject(); + if (!aj) + goto fail; + if (!cJSON_AddItemToArray(actions, aj)) { + cJSON_Delete(aj); + goto fail; + } + if ((a->type != TS_AUTO_ACT_TEMPLATE_REF && + !cJSON_AddStringToObject(aj, "type", types[a->type])) || + !fields_write(aj, a, common, sizeof(common) / sizeof(field)) || + (a->type != TS_AUTO_ACT_TEMPLATE_REF && + !fields_write(aj, a, by_type[a->type].fields, by_type[a->type].count)) || + !cJSON_AddStringToObject(aj, "repeat_mode", repeats[a->repeat_mode])) + goto fail; + if (a->condition.has_condition) { + cJSON *cj = + condition_write(a->condition.variable, a->condition.op, &a->condition.value); + if (!cj) + goto fail; + if (!cJSON_AddItemToObject(aj, "condition", cj)) { + cJSON_Delete(cj); + goto fail; + } + } + if (a->type == TS_AUTO_ACT_SET_VAR) { + if (!cJSON_AddNumberToObject(aj, "value_type", a->set_var.value.type)) + goto fail; + cJSON *v = value_write(&a->set_var.value); + if (!v) + goto fail; + if (!cJSON_AddItemToObject(aj, "value", v)) { + cJSON_Delete(v); + goto fail; + } + } + } + return j; +fail: + cJSON_Delete(j); + return NULL; +} diff --git a/components/ts_automation/src/ts_rule_engine.c b/components/ts_automation/src/ts_rule_engine.c index cba637d..67bf7d3 100644 --- a/components/ts_automation/src/ts_rule_engine.c +++ b/components/ts_automation/src/ts_rule_engine.c @@ -1,3 +1,7 @@ +#include "ts_rule_codec.h" +#include "ts_rule_store.h" +#include "ts_ssh_commands_config.h" +#include "ts_ssh_service.h" /** * @file ts_rule_engine.c * @brief TianShanOS 自动化引擎 - 规则引擎实现 @@ -71,7 +75,15 @@ typedef struct { int count; // 当前规则数量 int capacity; // 最大容量 SemaphoreHandle_t mutex; // 访问互斥锁 - bool initialized; // 初始化标志 + bool initialized; + bool loaded, recovery_error; + int source; + uint32_t next_instance; + unsigned retired; + SemaphoreHandle_t transaction; + struct { + bool committing, executing, readonly; + } meta[CONFIG_TS_AUTOMATION_MAX_RULES]; ts_rule_engine_stats_t stats; // 统计信息 } ts_rule_engine_ctx_t; @@ -83,6 +95,75 @@ static ts_rule_engine_ctx_t s_rule_ctx = { .initialized = false, }; +typedef struct { + unsigned refs; + bool retired; + ts_auto_condition_t *conditions; + ts_auto_action_t *actions; +} rule_payload_t; +static void payload_free(rule_payload_t *p) { + if (p) { + free(p->conditions); + free(p->actions); + free(p); + } +} +static rule_payload_t *payload_adopt(ts_auto_rule_t *r) { + rule_payload_t *p = heap_caps_calloc(1, sizeof(*p), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (p) { + p->conditions = r->conditions.conditions; + p->actions = r->actions; + r->lease = p; + } + return p; +} +static int find_rule_index(const char *id); +void ts_rule_resolve_presentation(ts_auto_rule_t *r) { + bool service = false, unresolved = false; + for (unsigned i = 0; i < r->action_count; ++i) { + ts_auto_action_t *a = &r->actions[i]; + ts_action_template_t *tpl = NULL; + if (a->template_id[0]) { + tpl = heap_caps_calloc(1, sizeof(*tpl), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!tpl || ts_action_template_get(a->template_id, tpl) != ESP_OK) { + free(tpl); + unresolved = true; + continue; + } + a = &tpl->action; + } + if (a->type == TS_AUTO_ACT_SSH_CMD_REF) { + ts_ssh_command_config_t *cmd = + heap_caps_calloc(1, sizeof(*cmd), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!cmd || ts_ssh_commands_config_get(a->ssh_ref.cmd_id, cmd) != ESP_OK) + unresolved = true; + else + service |= cmd->service_mode; + free(cmd); + } + free(tpl); + } + if (!(r->presentation_fields & 1)) + r->show_on_dashboard = (r->enabled && r->manual_trigger) || service; + if (!(r->presentation_fields & 2)) + r->allow_manual_trigger = r->manual_trigger || service; + r->reference_unresolved = unresolved; + if (!unresolved) + r->presentation_fields = 3; + if (r->lease && s_rule_ctx.initialized) { + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + int index = find_rule_index(r->id); + if (index >= 0 && s_rule_ctx.rules[index].revision == r->revision && + s_rule_ctx.rules[index].instance == r->instance) { + s_rule_ctx.rules[index].show_on_dashboard = r->show_on_dashboard; + s_rule_ctx.rules[index].allow_manual_trigger = r->allow_manual_trigger; + s_rule_ctx.rules[index].reference_unresolved = unresolved; + s_rule_ctx.rules[index].presentation_fields = r->presentation_fields; + } + xSemaphoreGive(s_rule_ctx.mutex); + } +} + /*===========================================================================*/ /* 执行历史环形缓冲区 */ /*===========================================================================*/ @@ -252,8 +333,11 @@ esp_err_t ts_rule_engine_init(void) memset(s_rule_ctx.rules, 0, alloc_size); // 创建互斥锁 - s_rule_ctx.mutex = xSemaphoreCreateMutex(); - if (!s_rule_ctx.mutex) { + if (!s_rule_ctx.mutex) + s_rule_ctx.mutex = xSemaphoreCreateMutex(); + if (!s_rule_ctx.transaction) + s_rule_ctx.transaction = xSemaphoreCreateRecursiveMutex(); + if (!s_rule_ctx.mutex || !s_rule_ctx.transaction) { free(s_rule_ctx.rules); s_rule_ctx.rules = NULL; ESP_LOGE(TAG, "Failed to create mutex"); @@ -309,40 +393,28 @@ void ts_rule_deferred_load_task(void *arg) esp_err_t ts_rule_engine_deinit(void) { - if (!s_rule_ctx.initialized) { - return ESP_OK; - } - - ESP_LOGI(TAG, "Deinitializing rule engine"); - - // 释放规则中的动态分配内存 - for (int i = 0; i < s_rule_ctx.count; i++) { - if (s_rule_ctx.rules[i].conditions.conditions) { - free(s_rule_ctx.rules[i].conditions.conditions); - } - if (s_rule_ctx.rules[i].actions) { - free(s_rule_ctx.rules[i].actions); - } - } - - if (s_rule_ctx.mutex) { - vSemaphoreDelete(s_rule_ctx.mutex); - s_rule_ctx.mutex = NULL; - } - - if (s_rule_ctx.rules) { - if (heap_caps_get_allocated_size(s_rule_ctx.rules) > 0) { - heap_caps_free(s_rule_ctx.rules); - } else { - free(s_rule_ctx.rules); - } - s_rule_ctx.rules = NULL; + if (!s_rule_ctx.initialized) + return ESP_ERR_INVALID_STATE; + xSemaphoreTakeRecursive(s_rule_ctx.transaction, portMAX_DELAY); + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + bool busy = s_rule_ctx.retired != 0; + for (int i = 0; i < s_rule_ctx.count; ++i) + busy |= ((rule_payload_t *)s_rule_ctx.rules[i].lease)->refs != 0 || + s_rule_ctx.meta[i].executing; + if (busy) { + xSemaphoreGive(s_rule_ctx.mutex); + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + return ESP_ERR_INVALID_STATE; } - - s_rule_ctx.count = 0; - s_rule_ctx.capacity = 0; s_rule_ctx.initialized = false; - + xSemaphoreGive(s_rule_ctx.mutex); + for (int i = 0; i < s_rule_ctx.count; ++i) + payload_free(s_rule_ctx.rules[i].lease); + free(s_rule_ctx.rules); + s_rule_ctx.rules = NULL; + s_rule_ctx.count = 0; + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + /* Retain small mutexes for late rejected callers. */ return ESP_OK; } @@ -350,235 +422,275 @@ esp_err_t ts_rule_engine_deinit(void) /* 规则管理 */ /*===========================================================================*/ -esp_err_t ts_rule_register(const ts_auto_rule_t *rule) -{ - if (!rule || !rule->id[0]) { +/* Readers pin only the immutable arrays; scalar metadata is copied in the short lock. */ +esp_err_t ts_rule_acquire(const char *id, ts_auto_rule_t *out) { + if (!id || !out || !s_rule_ctx.initialized) return ESP_ERR_INVALID_ARG; - } - - if (!s_rule_ctx.initialized) { - return ESP_ERR_INVALID_STATE; - } - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - // 检查是否已存在 - int idx = find_rule_index(rule->id); - if (idx >= 0) { - // 释放旧规则的动态内存 - if (s_rule_ctx.rules[idx].conditions.conditions) { - free(s_rule_ctx.rules[idx].conditions.conditions); - s_rule_ctx.rules[idx].conditions.conditions = NULL; - } - if (s_rule_ctx.rules[idx].actions) { - free(s_rule_ctx.rules[idx].actions); - s_rule_ctx.rules[idx].actions = NULL; - } - - // 复制基本数据 - strncpy(s_rule_ctx.rules[idx].id, rule->id, sizeof(s_rule_ctx.rules[idx].id) - 1); - strncpy(s_rule_ctx.rules[idx].name, rule->name, sizeof(s_rule_ctx.rules[idx].name) - 1); - strncpy(s_rule_ctx.rules[idx].icon, rule->icon, sizeof(s_rule_ctx.rules[idx].icon) - 1); - s_rule_ctx.rules[idx].enabled = rule->enabled; - s_rule_ctx.rules[idx].manual_trigger = rule->manual_trigger; - s_rule_ctx.rules[idx].cooldown_ms = rule->cooldown_ms; - s_rule_ctx.rules[idx].conditions.logic = rule->conditions.logic; - s_rule_ctx.rules[idx].conditions.count = 0; - s_rule_ctx.rules[idx].action_count = 0; - - // 深拷贝条件数组 - if (rule->conditions.count > 0 && rule->conditions.conditions) { - s_rule_ctx.rules[idx].conditions.conditions = heap_caps_calloc( - rule->conditions.count, sizeof(ts_auto_condition_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (s_rule_ctx.rules[idx].conditions.conditions) { - memcpy(s_rule_ctx.rules[idx].conditions.conditions, - rule->conditions.conditions, - rule->conditions.count * sizeof(ts_auto_condition_t)); - s_rule_ctx.rules[idx].conditions.count = rule->conditions.count; - } - } - - // 深拷贝动作数组 - if (rule->action_count > 0 && rule->actions) { - s_rule_ctx.rules[idx].actions = heap_caps_calloc( - rule->action_count, sizeof(ts_auto_action_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (s_rule_ctx.rules[idx].actions) { - memcpy(s_rule_ctx.rules[idx].actions, - rule->actions, - rule->action_count * sizeof(ts_auto_action_t)); - s_rule_ctx.rules[idx].action_count = rule->action_count; - } - } - - xSemaphoreGive(s_rule_ctx.mutex); - - // 保存到 NVS - ts_rules_save(); - - ESP_LOGD(TAG, "Updated rule: %s", rule->id); - return ESP_OK; - } - - // 检查容量 - if (s_rule_ctx.count >= s_rule_ctx.capacity) { + int i = find_rule_index(id); + if (i < 0) { xSemaphoreGive(s_rule_ctx.mutex); - ESP_LOGE(TAG, "Rule storage full"); - return ESP_ERR_NO_MEM; - } - - // 添加新规则 - 深拷贝 - ts_auto_rule_t *new_rule = &s_rule_ctx.rules[s_rule_ctx.count]; - memset(new_rule, 0, sizeof(ts_auto_rule_t)); - - // 复制基本数据 - strncpy(new_rule->id, rule->id, sizeof(new_rule->id) - 1); - strncpy(new_rule->name, rule->name, sizeof(new_rule->name) - 1); - strncpy(new_rule->icon, rule->icon, sizeof(new_rule->icon) - 1); - new_rule->enabled = rule->enabled; - new_rule->manual_trigger = rule->manual_trigger; - new_rule->cooldown_ms = rule->cooldown_ms; - new_rule->conditions.logic = rule->conditions.logic; - - // 深拷贝条件数组 - if (rule->conditions.count > 0 && rule->conditions.conditions) { - new_rule->conditions.conditions = heap_caps_calloc( - rule->conditions.count, sizeof(ts_auto_condition_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (new_rule->conditions.conditions) { - memcpy(new_rule->conditions.conditions, - rule->conditions.conditions, - rule->conditions.count * sizeof(ts_auto_condition_t)); - new_rule->conditions.count = rule->conditions.count; - } - } - - // 深拷贝动作数组 - if (rule->action_count > 0 && rule->actions) { - new_rule->actions = heap_caps_calloc( - rule->action_count, sizeof(ts_auto_action_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (new_rule->actions) { - memcpy(new_rule->actions, - rule->actions, - rule->action_count * sizeof(ts_auto_action_t)); - new_rule->action_count = rule->action_count; - } + return ESP_ERR_NOT_FOUND; } - - s_rule_ctx.count++; - + *out = s_rule_ctx.rules[i]; + ++((rule_payload_t *)out->lease)->refs; xSemaphoreGive(s_rule_ctx.mutex); - - // 保存到 NVS - ts_rules_save(); - - ESP_LOGI(TAG, "Registered rule: %s (%s)", rule->id, rule->name); return ESP_OK; } - -esp_err_t ts_rule_unregister(const char *id) -{ - if (!id || !s_rule_ctx.initialized) { - return ESP_ERR_INVALID_ARG; - } - +void ts_rule_release(ts_auto_rule_t *r) { + if (!r || !r->lease) + return; + rule_payload_t *p = r->lease; + bool destroy = false; xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - int idx = find_rule_index(id); - if (idx < 0) { - xSemaphoreGive(s_rule_ctx.mutex); - return ESP_ERR_NOT_FOUND; - } - - // 释放动态内存 - if (s_rule_ctx.rules[idx].conditions.conditions) { - free(s_rule_ctx.rules[idx].conditions.conditions); + if (--p->refs == 0 && p->retired) { + --s_rule_ctx.retired; + destroy = true; } - if (s_rule_ctx.rules[idx].actions) { - free(s_rule_ctx.rules[idx].actions); - } - - // 移动后续元素 - if (idx < s_rule_ctx.count - 1) { - memmove(&s_rule_ctx.rules[idx], - &s_rule_ctx.rules[idx + 1], - (s_rule_ctx.count - idx - 1) * sizeof(ts_auto_rule_t)); - } - s_rule_ctx.count--; - xSemaphoreGive(s_rule_ctx.mutex); - - // 保存到 NVS - ts_rules_save(); - - ESP_LOGD(TAG, "Unregistered rule: %s", id); - return ESP_OK; + if (destroy) + payload_free(p); + memset(r, 0, sizeof(*r)); } - -esp_err_t ts_rule_enable(const char *id) -{ - if (!id || !s_rule_ctx.initialized) { - return ESP_ERR_INVALID_ARG; - } - - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - int idx = find_rule_index(id); - if (idx < 0) { - xSemaphoreGive(s_rule_ctx.mutex); - return ESP_ERR_NOT_FOUND; +static bool same_config(const ts_auto_rule_t *a, const ts_auto_rule_t *b) { + return !strcmp(a->id, b->id) && !strcmp(a->name, b->name) && !strcmp(a->icon, b->icon) && + a->enabled == b->enabled && a->manual_trigger == b->manual_trigger && + a->show_on_dashboard == b->show_on_dashboard && + a->allow_manual_trigger == b->allow_manual_trigger && + a->presentation_fields == b->presentation_fields && a->cooldown_ms == b->cooldown_ms && + a->conditions.logic == b->conditions.logic && + a->conditions.count == b->conditions.count && a->action_count == b->action_count && + (!a->conditions.count || !memcmp(a->conditions.conditions, b->conditions.conditions, + a->conditions.count * sizeof(ts_auto_condition_t))) && + (!a->action_count || + !memcmp(a->actions, b->actions, a->action_count * sizeof(ts_auto_action_t))); +} +static bool protected_bindings(const ts_auto_rule_t *old, const ts_auto_rule_t *next) { + bool actions_changed = !next || old->action_count != next->action_count || + (old->action_count && memcmp(old->actions, next->actions, old->action_count * sizeof(*old->actions))); + if (actions_changed && ts_ssh_service_rule_protected(old->id)) return true; + for (unsigned i = 0; i < old->action_count; i++) { + const ts_auto_action_t *a = &old->actions[i]; + bool retained = false; + if (next) + for (unsigned n = 0; n < next->action_count; n++) { + const ts_auto_action_t *b = &next->actions[n]; + if (a->template_id[0]) + retained |= !strcmp(a->template_id, b->template_id); + else if (a->type == TS_AUTO_ACT_SSH_CMD_REF) + retained |= b->type == a->type && !strcmp(a->ssh_ref.cmd_id, b->ssh_ref.cmd_id); + } + if (retained) + continue; + ts_action_template_t *tpl = NULL; + if (a->template_id[0]) { + tpl = heap_caps_malloc(sizeof(*tpl), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!tpl) + return true; + esp_err_t lookup = ts_action_template_get(a->template_id, tpl); + if (lookup != ESP_OK) { + free(tpl); + /* Missing configuration is not proof that a remote service ended. + * Without the old binding, conservatively consult independent runs. */ + if (lookup != ESP_ERR_NOT_FOUND || ts_ssh_service_any_in_use()) return true; + continue; + } + a = &tpl->action; + } + bool busy = a->type == TS_AUTO_ACT_SSH_CMD_REF && + ts_ssh_service_command_protected(a->ssh_ref.cmd_id); + free(tpl); + if (busy) + return true; } - - s_rule_ctx.rules[idx].enabled = true; - - xSemaphoreGive(s_rule_ctx.mutex); - - // 保存状态变更到 NVS - ts_rules_save(); - - return ESP_OK; + return false; } - -esp_err_t ts_rule_disable(const char *id) -{ - if (!id || !s_rule_ctx.initialized) { +esp_err_t ts_rule_commit(const ts_auto_rule_t *input, const char *id, uint32_t expected, + ts_rule_commit_result_t *result) { + ts_rule_commit_result_t local = {.error_code = "invalid_argument"}; + if (!result) + result = &local; + *result = local; + if (!ts_rule_id_valid(id) || !s_rule_ctx.initialized) return ESP_ERR_INVALID_ARG; + xSemaphoreTakeRecursive(s_rule_ctx.transaction, portMAX_DELAY); + ts_auto_rule_t candidate = {0}; + if (input) { + cJSON *j = ts_rule_encode(input); + if (!j) { + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + return ESP_ERR_NO_MEM; + } + esp_err_t ret = ts_rule_decode(j, &candidate); + cJSON_Delete(j); + if (ret != ESP_OK) { + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + return ret; + } + ts_rule_resolve_presentation(&candidate); + if (strcmp(candidate.id, id)) { + ts_rule_dispose(&candidate); + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + return ESP_ERR_INVALID_ARG; + } + if (!payload_adopt(&candidate)) { + ts_rule_dispose(&candidate); + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + return ESP_ERR_NO_MEM; + } } - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - int idx = find_rule_index(id); - if (idx < 0) { + int i = find_rule_index(id); + esp_err_t ret = ESP_OK; + if (!s_rule_ctx.loaded || s_rule_ctx.recovery_error) { + ret = ESP_ERR_INVALID_STATE; + result->error_code = "recovery_required"; + } else if ((i < 0 && expected != 0) || (i >= 0 && expected != s_rule_ctx.rules[i].revision)) { + ret = ESP_ERR_INVALID_STATE; + result->error_code = "revision_conflict"; + } else if (i < 0 && !input) { + ret = ESP_ERR_NOT_FOUND; + } else if (i < 0 && s_rule_ctx.count == s_rule_ctx.capacity) { + ret = ESP_ERR_NO_MEM; + result->error_code = "capacity"; + } else if (i >= 0 && s_rule_ctx.meta[i].readonly) { + ret = ESP_ERR_NOT_SUPPORTED; + result->error_code = "source_read_only"; + } else if (i >= 0 && s_rule_ctx.retired && + ((rule_payload_t *)s_rule_ctx.rules[i].lease)->refs) { + ret = ESP_ERR_INVALID_STATE; + result->error_code = "busy_retired_config"; + } else if (i >= 0 && !input && s_rule_ctx.meta[i].executing) { + ret = ESP_ERR_INVALID_STATE; + result->error_code = "execution_busy"; + } else if (i >= 0 && input && same_config(&candidate, &s_rule_ctx.rules[i])) { + result->applied = result->durable = 1; + result->mirror_synced = -1; + result->revision = s_rule_ctx.rules[i].revision; + result->error_code = "no_change"; xSemaphoreGive(s_rule_ctx.mutex); - return ESP_ERR_NOT_FOUND; + goto done; } - - s_rule_ctx.rules[idx].enabled = false; - + if (ret != ESP_OK) { + xSemaphoreGive(s_rule_ctx.mutex); + goto done; + } + if (i >= 0) + s_rule_ctx.meta[i].committing = true; + if (i >= 0 && s_rule_ctx.rules[i].revision == UINT32_MAX) { + s_rule_ctx.meta[i].committing = false; + result->error_code = "revision_exhausted"; + ret = ESP_ERR_INVALID_STATE; + xSemaphoreGive(s_rule_ctx.mutex); + goto done; + } + candidate.revision = i >= 0 ? s_rule_ctx.rules[i].revision + 1 : 1; xSemaphoreGive(s_rule_ctx.mutex); - - // 保存状态变更到 NVS - ts_rules_save(); - - return ESP_OK; -} - -const ts_auto_rule_t *ts_rule_get(const char *id) -{ - if (!id || !s_rule_ctx.initialized) { - return NULL; + ts_ssh_binding_lock(); + if (i >= 0 && protected_bindings(&s_rule_ctx.rules[i], input ? &candidate : NULL)) { + ts_ssh_binding_unlock(); + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + s_rule_ctx.meta[i].committing = false; + xSemaphoreGive(s_rule_ctx.mutex); + result->error_code = "service_busy"; + ret = ESP_ERR_INVALID_STATE; + goto done; + } + /* The edit gate keeps payloads alive; copy scalar metadata under the rule + * lock so cold presentation resolution cannot race the durable snapshot. */ + ts_auto_rule_t *persisted = s_rule_ctx.count + ? heap_caps_malloc(s_rule_ctx.count * sizeof(*persisted), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) + : NULL; + if (s_rule_ctx.count && !persisted) { + ts_ssh_binding_unlock(); + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + if (i >= 0) + s_rule_ctx.meta[i].committing = false; + xSemaphoreGive(s_rule_ctx.mutex); + result->error_code = "no_memory"; + ret = ESP_ERR_NO_MEM; + goto done; } - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - int idx = find_rule_index(id); - const ts_auto_rule_t *rule = (idx >= 0) ? &s_rule_ctx.rules[idx] : NULL; - + if (persisted) + memcpy(persisted, s_rule_ctx.rules, s_rule_ctx.count * sizeof(*persisted)); + xSemaphoreGive(s_rule_ctx.mutex); + ts_rule_commit_t stored; + ret = ts_rule_store_commit(persisted, s_rule_ctx.count, input ? &candidate : NULL, id, + s_rule_ctx.source, &stored); + free(persisted); + result->applied = stored.applied; + result->durable = stored.durable; + result->mirror_synced = stored.mirror_synced; + result->error_code = stored.error_code; + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + if (stored.applied < 0) + s_rule_ctx.recovery_error = true; + rule_payload_t *old = NULL; + if (ret == ESP_OK) { + if (i >= 0) { + old = s_rule_ctx.rules[i].lease; + candidate.last_trigger_ms = s_rule_ctx.rules[i].last_trigger_ms; + candidate.trigger_count = s_rule_ctx.rules[i].trigger_count; + candidate.instance = s_rule_ctx.rules[i].instance; + } else { + i = s_rule_ctx.count++; + memset(&s_rule_ctx.meta[i], 0, sizeof(s_rule_ctx.meta[i])); + candidate.instance = ++s_rule_ctx.next_instance; + } + if (input) { + s_rule_ctx.rules[i] = candidate; + candidate.lease = NULL; + result->revision = s_rule_ctx.rules[i].revision; + } else { + memmove(s_rule_ctx.rules + i, s_rule_ctx.rules + i + 1, + (s_rule_ctx.count - i - 1) * sizeof(ts_auto_rule_t)); + memmove(s_rule_ctx.meta + i, s_rule_ctx.meta + i + 1, + (s_rule_ctx.count - i - 1) * sizeof(s_rule_ctx.meta[0])); + --s_rule_ctx.count; + i = -1; + } + if (old && old->refs) { + old->retired = true; + ++s_rule_ctx.retired; + old = NULL; + } + } + if (i >= 0) + s_rule_ctx.meta[i].committing = false; xSemaphoreGive(s_rule_ctx.mutex); - return rule; + payload_free(old); + ts_ssh_binding_unlock(); +done: + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + payload_free(candidate.lease); + return ret; +} +esp_err_t ts_rule_register(const ts_auto_rule_t *r) { + return r ? ts_rule_commit(r, r->id, r->revision, NULL) : ESP_ERR_INVALID_ARG; } +esp_err_t ts_rule_unregister(const char *id) { + ts_auto_rule_t r; + esp_err_t e = ts_rule_acquire(id, &r); + if (e != ESP_OK) + return e; + uint32_t v = r.revision; + ts_rule_release(&r); + return ts_rule_commit(NULL, id, v, NULL); +} +static esp_err_t set_enabled(const char *id, bool enabled) { + ts_auto_rule_t r; + esp_err_t e = ts_rule_acquire(id, &r); + if (e != ESP_OK) + return e; + r.enabled = enabled; + e = ts_rule_commit(&r, id, r.revision, NULL); + ts_rule_release(&r); + return e; +} +esp_err_t ts_rule_enable(const char *id) { return set_enabled(id, true); } +esp_err_t ts_rule_disable(const char *id) { return set_enabled(id, false); } int ts_rule_count(void) { @@ -611,6 +723,13 @@ bool ts_rule_eval_condition(const ts_auto_condition_t *condition) return false; } + /* Missing/non-numeric values must not compare equal after a failed coercion. */ + bool lhs_numeric = var_value.type >= TS_AUTO_VAL_BOOL && var_value.type <= TS_AUTO_VAL_FLOAT; + bool rhs_numeric = + condition->value.type >= TS_AUTO_VAL_BOOL && condition->value.type <= TS_AUTO_VAL_FLOAT; + if (var_value.type == TS_AUTO_VAL_NULL || condition->value.type == TS_AUTO_VAL_NULL || + (var_value.type != condition->value.type && !(lhs_numeric && rhs_numeric))) + return false; // 执行比较 int cmp = compare_values(&var_value, &condition->value); @@ -683,85 +802,113 @@ bool ts_rule_eval_condition_group(const ts_auto_condition_group_t *group) /* 规则评估 */ /*===========================================================================*/ -esp_err_t ts_rule_evaluate(const char *id, bool *triggered) -{ - if (!id || !triggered || !s_rule_ctx.initialized) { - return ESP_ERR_INVALID_ARG; - } - +static esp_err_t execute_rule(const char *id, bool manual, bool *triggered) { + if (!ts_action_manager_accepting()) return ESP_ERR_INVALID_STATE; *triggered = false; - - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - int idx = find_rule_index(id); - if (idx < 0) { - xSemaphoreGive(s_rule_ctx.mutex); - return ESP_ERR_NOT_FOUND; - } - - ts_auto_rule_t *rule = &s_rule_ctx.rules[idx]; - - // 检查是否启用 - if (!rule->enabled) { - xSemaphoreGive(s_rule_ctx.mutex); + ts_auto_rule_t r; + esp_err_t ret = ts_rule_acquire(id, &r); + if (ret != ESP_OK) + return ret; + if (manual && (r.reference_unresolved || r.presentation_fields != 3)) + ts_rule_resolve_presentation(&r); + if (!r.enabled || (!manual && r.manual_trigger) || (manual && !r.allow_manual_trigger)) { + ts_rule_release(&r); + return manual ? ESP_ERR_INVALID_STATE : ESP_OK; + } + if (!manual && !ts_rule_eval_condition_group(&r.conditions)) { + ts_rule_release(&r); return ESP_OK; } - - // 检查冷却时间 - int64_t now_ms = esp_timer_get_time() / 1000; - if (rule->cooldown_ms > 0 && rule->last_trigger_ms > 0) { - if ((now_ms - rule->last_trigger_ms) < rule->cooldown_ms) { - xSemaphoreGive(s_rule_ctx.mutex); - return ESP_OK; // 还在冷却中 + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + int preliminary = find_rule_index(id); + bool unavailable = preliminary < 0 || !s_rule_ctx.loaded || s_rule_ctx.recovery_error || + s_rule_ctx.meta[preliminary].committing || + s_rule_ctx.meta[preliminary].executing || + (!manual && r.cooldown_ms && r.last_trigger_ms && + esp_timer_get_time() / 1000 - r.last_trigger_ms < r.cooldown_ms); + xSemaphoreGive(s_rule_ctx.mutex); + if (unavailable) { + ts_rule_release(&r); + return manual ? ESP_ERR_INVALID_STATE : ESP_OK; + } + for (unsigned n = 0; n < r.action_count; n++) { + if (r.actions[n].type == TS_AUTO_ACT_SSH_CMD_REF && + !ts_ssh_service_start_admissible(r.actions[n].ssh_ref.cmd_id)) { + ts_rule_release(&r); + return manual ? ESP_ERR_INVALID_STATE : ESP_OK; } } - + /* Freeze all referenced actions/SSH bindings once at admission. No allocation + * on unmatched evaluations; queue entries retain their own binding lease. */ + ts_auto_action_t *frozen = + heap_caps_calloc(r.action_count, sizeof(*frozen), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!frozen) { + ts_rule_release(&r); + return ESP_ERR_NO_MEM; + } + ts_ssh_binding_lock(); + unsigned prepared = 0; + for (; prepared < r.action_count; ++prepared) { + ret = ts_action_snapshot(&r.actions[prepared], &frozen[prepared]); + if (ret != ESP_OK) + break; + } + if (ret != ESP_OK) { + ts_ssh_binding_unlock(); + for (unsigned n = 0; n < prepared; n++) + ts_action_snapshot_release(&frozen[n]); + free(frozen); + ts_rule_release(&r); + return ret; + } + int64_t now = esp_timer_get_time() / 1000; + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + int i = find_rule_index(id); + bool valid = i >= 0 && !s_rule_ctx.recovery_error && s_rule_ctx.loaded && + !s_rule_ctx.meta[i].committing && !s_rule_ctx.meta[i].executing && + s_rule_ctx.rules[i].revision == r.revision && + s_rule_ctx.rules[i].instance == r.instance; + if (valid && !manual && r.cooldown_ms && s_rule_ctx.rules[i].last_trigger_ms && + now - s_rule_ctx.rules[i].last_trigger_ms < r.cooldown_ms) + valid = false; + if (valid) + s_rule_ctx.meta[i].executing = true; xSemaphoreGive(s_rule_ctx.mutex); - - // 评估条件(在锁外执行,避免死锁) - bool conditions_met = ts_rule_eval_condition_group(&rule->conditions); - - if (conditions_met) { - // 执行动作 - ESP_LOGI(TAG, "Rule '%s' triggered", rule->id); - - int success_count = 0, fail_count = 0; - if (rule->actions && rule->action_count > 0) { - execute_actions_with_stats(rule->actions, rule->action_count, - &success_count, &fail_count); - } - - // 更新触发时间和计数 - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - rule->last_trigger_ms = now_ms; - rule->trigger_count++; - s_rule_ctx.stats.total_triggers++; - s_rule_ctx.stats.total_actions += rule->action_count; - s_rule_ctx.stats.failed_actions += fail_count; - - // 记录执行历史 - ts_rule_exec_status_t status; - char msg[TS_RULE_EXEC_MSG_LEN]; - if (fail_count == 0) { - status = TS_RULE_EXEC_SUCCESS; - snprintf(msg, sizeof(msg), "%d actions OK", success_count); - } else if (success_count == 0) { - status = TS_RULE_EXEC_FAILED; - snprintf(msg, sizeof(msg), "all %d actions failed", fail_count); - } else { - status = TS_RULE_EXEC_PARTIAL; - snprintf(msg, sizeof(msg), "%d/%d actions failed", - fail_count, success_count + fail_count); - } - record_execution(rule->id, status, TS_RULE_TRIGGER_CONDITION, - msg, (uint8_t)rule->action_count, (uint8_t)fail_count); - - xSemaphoreGive(s_rule_ctx.mutex); - - *triggered = true; + if (valid) + for (unsigned n = 0; n < r.action_count; ++n) ts_action_snapshot_owner(&frozen[n], r.id); + ts_ssh_binding_unlock(); + if (!valid) { + for (unsigned n = 0; n < r.action_count; n++) + ts_action_snapshot_release(&frozen[n]); + free(frozen); + ts_rule_release(&r); + return manual ? ESP_ERR_INVALID_STATE : ESP_OK; + } + int success = 0, failed = 0; + ret = execute_actions_with_stats(frozen, r.action_count, &success, &failed); + for (unsigned n = 0; n < r.action_count; n++) + ts_action_snapshot_release(&frozen[n]); + free(frozen); + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + i = find_rule_index(id); + if (i >= 0 && s_rule_ctx.rules[i].instance == r.instance) { + s_rule_ctx.meta[i].executing = false; + s_rule_ctx.rules[i].last_trigger_ms = now; + ++s_rule_ctx.rules[i].trigger_count; + ++s_rule_ctx.stats.total_triggers; + record_execution(id, failed ? TS_RULE_EXEC_FAILED : TS_RULE_EXEC_SUCCESS, + manual ? TS_RULE_TRIGGER_MANUAL : TS_RULE_TRIGGER_CONDITION, + failed ? "action failed" : "actions accepted", r.action_count, failed); } - - return ESP_OK; + xSemaphoreGive(s_rule_ctx.mutex); + *triggered = true; + ts_rule_release(&r); + return ret; +} +esp_err_t ts_rule_evaluate(const char *id, bool *triggered) { + if (!triggered) + return ESP_ERR_INVALID_ARG; + return execute_rule(id, false, triggered); } int ts_rule_evaluate_all(void) @@ -804,74 +951,9 @@ int ts_rule_evaluate_all(void) return triggered; } -esp_err_t ts_rule_trigger(const char *id) -{ - if (!id || !s_rule_ctx.initialized) { - return ESP_ERR_INVALID_ARG; - } - - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - int idx = find_rule_index(id); - if (idx < 0) { - xSemaphoreGive(s_rule_ctx.mutex); - return ESP_ERR_NOT_FOUND; - } - - ts_auto_rule_t *rule = &s_rule_ctx.rules[idx]; - int action_count = rule->action_count; - char rule_id_copy[TS_AUTO_NAME_MAX_LEN]; - strncpy(rule_id_copy, rule->id, sizeof(rule_id_copy) - 1); - rule_id_copy[sizeof(rule_id_copy) - 1] = '\0'; - - ESP_LOGI(TAG, "Manually triggering rule: %s (actions=%p, count=%d)", - rule->id, (void*)rule->actions, rule->action_count); - - // 执行动作 - int success_count = 0, fail_count = 0; - if (rule->actions && rule->action_count > 0) { - ESP_LOGI(TAG, "Executing %d actions for rule %s", rule->action_count, rule->id); - for (int i = 0; i < rule->action_count; i++) { - ESP_LOGI(TAG, " Action[%d]: type=%d, template=%s, delay=%d", - i, rule->actions[i].type, - rule->actions[i].template_id[0] ? rule->actions[i].template_id : "(none)", - rule->actions[i].delay_ms); - } - xSemaphoreGive(s_rule_ctx.mutex); - execute_actions_with_stats(rule->actions, rule->action_count, - &success_count, &fail_count); - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - ESP_LOGI(TAG, "Actions execution complete: success=%d, fail=%d", success_count, fail_count); - } else { - ESP_LOGW(TAG, "Rule %s has no actions (actions=%p, count=%d)", - rule->id, (void*)rule->actions, rule->action_count); - } - - rule->last_trigger_ms = esp_timer_get_time() / 1000; - rule->trigger_count++; - s_rule_ctx.stats.total_triggers++; - s_rule_ctx.stats.total_actions += action_count; - s_rule_ctx.stats.failed_actions += fail_count; - - // 记录执行历史 - ts_rule_exec_status_t status; - char msg[TS_RULE_EXEC_MSG_LEN]; - if (fail_count == 0) { - status = TS_RULE_EXEC_SUCCESS; - snprintf(msg, sizeof(msg), "%d actions OK (manual)", success_count); - } else if (success_count == 0) { - status = TS_RULE_EXEC_FAILED; - snprintf(msg, sizeof(msg), "all %d failed (manual)", fail_count); - } else { - status = TS_RULE_EXEC_PARTIAL; - snprintf(msg, sizeof(msg), "%d/%d failed (manual)", - fail_count, success_count + fail_count); - } - record_execution(rule_id_copy, status, TS_RULE_TRIGGER_MANUAL, - msg, (uint8_t)action_count, (uint8_t)fail_count); - - xSemaphoreGive(s_rule_ctx.mutex); - return ESP_OK; +esp_err_t ts_rule_trigger(const char *id) { + bool triggered; + return execute_rule(id, true, &triggered); } /*===========================================================================*/ @@ -1032,7 +1114,7 @@ static esp_err_t execute_cli_action(const ts_auto_action_t *action) } const char *command = action->cli.command; - ESP_LOGI(TAG, "CLI action: command=%s (queued)", command); + ESP_LOGD(TAG, "CLI action queued (%u bytes)", (unsigned)strlen(command)); if (!command || command[0] == '\0') { ESP_LOGE(TAG, "Empty CLI command"); @@ -1160,10 +1242,10 @@ static esp_err_t execute_ssh_action(const ts_auto_action_t *action) if (ret == ESP_OK) { ESP_LOGI(TAG, "SSH command exit code: %d", result.exit_code); if (result.stdout_data && result.stdout_len > 0) { - ESP_LOGD(TAG, "SSH stdout: %.*s", (int)result.stdout_len, result.stdout_data); + ESP_LOGD(TAG, "SSH stdout bytes: %u", (unsigned)result.stdout_len); } if (result.stderr_data && result.stderr_len > 0) { - ESP_LOGW(TAG, "SSH stderr: %.*s", (int)result.stderr_len, result.stderr_data); + ESP_LOGW(TAG, "SSH stderr bytes: %u", (unsigned)result.stderr_len); } // 存储 exit_code 到变量(使用 host_ref 作为变量前缀) @@ -1261,12 +1343,18 @@ esp_err_t ts_action_execute(const ts_auto_action_t *action) esp_err_t ret = ESP_OK; ts_action_result_t result = {0}; + if (action->runtime_snapshot) { + ts_auto_action_t queued = *action; + queued.delay_ms = 0; /* Rule sequencer already applied this delay. */ + return action->async ? ts_action_queue(&queued, NULL, NULL, 5) + : ts_action_manager_execute(&queued, &result); + } /* 如果有 template_id,使用模板执行(模板包含完整的动作数据) */ if (action->template_id[0] != '\0') { ESP_LOGD(TAG, "Executing action via template: %s", action->template_id); ret = ts_action_template_execute(action->template_id, &result); if (ret != ESP_OK) { - ESP_LOGW(TAG, "Template action failed: %s - %s", action->template_id, result.output); + ESP_LOGW(TAG, "Template action failed: %s (code=%d)", action->template_id, ret); } s_rule_ctx.stats.total_actions++; if (ret != ESP_OK) { @@ -1363,11 +1451,21 @@ static bool check_action_condition(const ts_auto_action_t *action) /** * @brief Execute a single action with repeat support */ +/* Delays/repeat waits cooperate with stop without abandoning rule ownership. */ +static bool rule_wait(uint32_t ms) { + while (ms && ts_action_manager_accepting()) { + uint32_t slice = ms > 100 ? 100 : ms; + vTaskDelay(pdMS_TO_TICKS(slice)); + ms -= slice; + } + return ts_action_manager_accepting(); +} static esp_err_t execute_action_with_repeat(const ts_auto_action_t *action, ts_action_result_cb_t callback, void *user_data) { esp_err_t ret = ESP_OK; + if (!ts_action_manager_accepting()) return ESP_ERR_INVALID_STATE; // 先检查动作级别的条件 if (!check_action_condition(action)) { @@ -1393,6 +1491,7 @@ static esp_err_t execute_action_with_repeat(const ts_auto_action_t *action, ESP_LOGI(TAG, "Repeat action %d times, interval=%dms", count, interval); for (uint8_t i = 0; i < count; i++) { + if (!ts_action_manager_accepting()) return ESP_ERR_INVALID_STATE; // 每次重复前检查条件 if (!check_action_condition(action)) { ESP_LOGI(TAG, "Repeat stopped: condition no longer met"); @@ -1406,7 +1505,7 @@ static esp_err_t execute_action_with_repeat(const ts_auto_action_t *action, // 最后一次不需要等待 if (i < count - 1 && interval > 0) { - vTaskDelay(pdMS_TO_TICKS(interval)); + if (!rule_wait(interval)) return ESP_ERR_INVALID_STATE; } } break; @@ -1420,14 +1519,14 @@ static esp_err_t execute_action_with_repeat(const ts_auto_action_t *action, ESP_LOGI(TAG, "Repeat while condition true, interval=%dms, max=%d", interval, max_iterations); - while (check_action_condition(action) && iterations < max_iterations) { + while (ts_action_manager_accepting() && check_action_condition(action) && iterations < max_iterations) { ret = ts_action_execute(action); if (callback) { callback(action, ret, user_data); } iterations++; - vTaskDelay(pdMS_TO_TICKS(interval)); + if (!rule_wait(interval)) return ESP_ERR_INVALID_STATE; } if (iterations >= max_iterations) { @@ -1462,6 +1561,7 @@ static esp_err_t execute_actions_with_stats(const ts_auto_action_t *actions, int ESP_LOGI(TAG, "Executing %d actions sequentially", count); for (int i = 0; i < count; i++) { + if (!ts_action_manager_accepting()) { fail += count - i; ret = ESP_ERR_INVALID_STATE; break; } ESP_LOGI(TAG, "Action [%d/%d]: type=%d, template=%s, delay=%dms", i + 1, count, actions[i].type, actions[i].template_id[0] ? actions[i].template_id : "(inline)", @@ -1470,7 +1570,7 @@ static esp_err_t execute_actions_with_stats(const ts_auto_action_t *actions, int // 动作前延迟 if (actions[i].delay_ms > 0) { ESP_LOGI(TAG, " Waiting %dms before action", actions[i].delay_ms); - vTaskDelay(pdMS_TO_TICKS(actions[i].delay_ms)); + if (!rule_wait(actions[i].delay_ms)) { fail += count - i; ret = ESP_ERR_INVALID_STATE; break; } } esp_err_t action_ret = execute_action_with_repeat(&actions[i], NULL, NULL); @@ -1507,7 +1607,7 @@ static esp_err_t execute_actions_with_stats(const ts_auto_action_t *actions, int } if (delay_after > 0) { ESP_LOGI(TAG, " Auto delay %dms after LED Matrix action", delay_after); - vTaskDelay(pdMS_TO_TICKS(delay_after)); + rule_wait(delay_after); } } } @@ -1550,6 +1650,7 @@ esp_err_t ts_rule_get_by_index(int index, ts_auto_rule_t *rule) } memcpy(rule, &s_rule_ctx.rules[index], sizeof(ts_auto_rule_t)); + ++((rule_payload_t *)rule->lease)->refs; xSemaphoreGive(s_rule_ctx.mutex); return ESP_OK; @@ -1685,894 +1786,262 @@ esp_err_t ts_rule_clear_exec_history(void) /** * @brief 操作符转字符串 */ -static const char *operator_to_str(ts_auto_operator_t op) -{ - switch (op) { - case TS_AUTO_OP_EQ: return "eq"; - case TS_AUTO_OP_NE: return "ne"; - case TS_AUTO_OP_GT: return "gt"; - case TS_AUTO_OP_GE: return "ge"; - case TS_AUTO_OP_LT: return "lt"; - case TS_AUTO_OP_LE: return "le"; - case TS_AUTO_OP_CONTAINS: return "contains"; - case TS_AUTO_OP_CHANGED: return "changed"; - default: return "eq"; - } -} - -/** - * @brief 字符串转操作符 - */ -static ts_auto_operator_t str_to_operator(const char *str) -{ - if (!str) return TS_AUTO_OP_EQ; - if (strcmp(str, "ne") == 0) return TS_AUTO_OP_NE; - if (strcmp(str, "gt") == 0) return TS_AUTO_OP_GT; - if (strcmp(str, "ge") == 0) return TS_AUTO_OP_GE; - if (strcmp(str, "lt") == 0) return TS_AUTO_OP_LT; - if (strcmp(str, "le") == 0) return TS_AUTO_OP_LE; - if (strcmp(str, "contains") == 0) return TS_AUTO_OP_CONTAINS; - if (strcmp(str, "changed") == 0) return TS_AUTO_OP_CHANGED; - return TS_AUTO_OP_EQ; -} - -/** - * @brief 动作类型转字符串 - */ -static const char *action_type_to_str(ts_auto_action_type_t type) -{ - switch (type) { - case TS_AUTO_ACT_LED: return "led"; - case TS_AUTO_ACT_GPIO: return "gpio"; - case TS_AUTO_ACT_DEVICE_CTRL: return "device_ctrl"; - case TS_AUTO_ACT_SSH_CMD_REF: return "ssh_cmd_ref"; - case TS_AUTO_ACT_CLI: return "cli"; - case TS_AUTO_ACT_WEBHOOK: return "webhook"; - case TS_AUTO_ACT_LOG: return "log"; - case TS_AUTO_ACT_SET_VAR: return "set_var"; - default: return "log"; - } +static esp_err_t decode_text(const char *text, ts_auto_rule_t *r) { + cJSON *j = cJSON_Parse(text); + if (!j) + return ESP_ERR_INVALID_ARG; + esp_err_t e = + ts_rule_decode(cJSON_HasObjectItem(j, "rule") ? cJSON_GetObjectItem(j, "rule") : j, r); + cJSON_Delete(j); + return e; } - -/** - * @brief 字符串转动作类型 - */ -static ts_auto_action_type_t str_to_action_type(const char *str) -{ - if (!str) return TS_AUTO_ACT_LOG; - if (strcmp(str, "led") == 0) return TS_AUTO_ACT_LED; - if (strcmp(str, "gpio") == 0) return TS_AUTO_ACT_GPIO; - if (strcmp(str, "device_ctrl") == 0) return TS_AUTO_ACT_DEVICE_CTRL; - if (strcmp(str, "ssh_cmd_ref") == 0) return TS_AUTO_ACT_SSH_CMD_REF; - if (strcmp(str, "cli") == 0) return TS_AUTO_ACT_CLI; - if (strcmp(str, "webhook") == 0) return TS_AUTO_ACT_WEBHOOK; - if (strcmp(str, "log") == 0) return TS_AUTO_ACT_LOG; - if (strcmp(str, "set_var") == 0) return TS_AUTO_ACT_SET_VAR; - return TS_AUTO_ACT_LOG; +static esp_err_t load_one(const char *path, ts_auto_rule_t *r, bool *encrypted) { + char *text = NULL; + size_t len = 0; + esp_err_t e = ts_config_pack_load_with_priority(path, &text, &len, encrypted); + if (e == ESP_OK) + e = decode_text(text, r); + free(text); + return e; } - -/** - * @brief 将值序列化为 JSON 对象 - */ -static cJSON *value_to_json(const ts_auto_value_t *val) -{ - switch (val->type) { - case TS_AUTO_VAL_BOOL: - return cJSON_CreateBool(val->bool_val); - case TS_AUTO_VAL_INT: - return cJSON_CreateNumber(val->int_val); - case TS_AUTO_VAL_FLOAT: - return cJSON_CreateNumber(val->float_val); - case TS_AUTO_VAL_STRING: - return cJSON_CreateString(val->str_val); - default: - return cJSON_CreateNull(); - } -} - -/** - * @brief 从 JSON 对象反序列化值 - */ -static void json_to_value(cJSON *json, ts_auto_value_t *val) -{ - if (!json || !val) return; - - if (cJSON_IsBool(json)) { - val->type = TS_AUTO_VAL_BOOL; - val->bool_val = cJSON_IsTrue(json); - } else if (cJSON_IsNumber(json)) { - // 判断是整数还是浮点数 - double d = json->valuedouble; - if (d == (int64_t)d && d >= INT32_MIN && d <= INT32_MAX) { - val->type = TS_AUTO_VAL_INT; - val->int_val = (int32_t)d; - } else { - val->type = TS_AUTO_VAL_FLOAT; - val->float_val = d; - } - } else if (cJSON_IsString(json)) { - val->type = TS_AUTO_VAL_STRING; - strncpy(val->str_val, json->valuestring, sizeof(val->str_val) - 1); - } -} - -/** - * @brief 将规则序列化为 JSON 字符串 - */ -static char *rule_to_json(const ts_auto_rule_t *rule) -{ - cJSON *root = cJSON_CreateObject(); - if (!root) return NULL; - - // 基本信息 - cJSON_AddStringToObject(root, "id", rule->id); - cJSON_AddStringToObject(root, "name", rule->name); - if (rule->icon[0]) { - cJSON_AddStringToObject(root, "icon", rule->icon); - } - cJSON_AddBoolToObject(root, "enabled", rule->enabled); - cJSON_AddBoolToObject(root, "manual_trigger", rule->manual_trigger); - cJSON_AddNumberToObject(root, "cooldown_ms", rule->cooldown_ms); - - // 条件组 - cJSON *conditions = cJSON_CreateObject(); - cJSON_AddStringToObject(conditions, "logic", - rule->conditions.logic == TS_AUTO_LOGIC_OR ? "or" : "and"); - - cJSON *cond_array = cJSON_CreateArray(); - for (int i = 0; i < rule->conditions.count; i++) { - const ts_auto_condition_t *c = &rule->conditions.conditions[i]; - cJSON *cond = cJSON_CreateObject(); - cJSON_AddStringToObject(cond, "variable", c->variable); - cJSON_AddStringToObject(cond, "operator", operator_to_str(c->op)); - cJSON_AddItemToObject(cond, "value", value_to_json(&c->value)); - cJSON_AddItemToArray(cond_array, cond); - } - cJSON_AddItemToObject(conditions, "items", cond_array); - cJSON_AddItemToObject(root, "conditions", conditions); - - // 动作数组 - cJSON *actions = cJSON_CreateArray(); - for (int i = 0; i < rule->action_count; i++) { - const ts_auto_action_t *a = &rule->actions[i]; - cJSON *action = cJSON_CreateObject(); - - cJSON_AddStringToObject(action, "type", action_type_to_str(a->type)); - cJSON_AddNumberToObject(action, "delay_ms", a->delay_ms); - - // 根据类型保存特定字段 - switch (a->type) { - case TS_AUTO_ACT_LED: - cJSON_AddStringToObject(action, "device", a->led.device); - cJSON_AddNumberToObject(action, "index", a->led.index); - cJSON_AddNumberToObject(action, "r", a->led.r); - cJSON_AddNumberToObject(action, "g", a->led.g); - cJSON_AddNumberToObject(action, "b", a->led.b); - if (a->led.effect[0]) { - cJSON_AddStringToObject(action, "effect", a->led.effect); - } - cJSON_AddNumberToObject(action, "duration_ms", a->led.duration_ms); - break; - - case TS_AUTO_ACT_GPIO: - cJSON_AddNumberToObject(action, "pin", a->gpio.pin); - cJSON_AddBoolToObject(action, "level", a->gpio.level); - cJSON_AddNumberToObject(action, "pulse_ms", a->gpio.pulse_ms); - break; - - case TS_AUTO_ACT_DEVICE_CTRL: - cJSON_AddStringToObject(action, "device", a->device.device); - cJSON_AddStringToObject(action, "action", a->device.action); - break; - - case TS_AUTO_ACT_CLI: - cJSON_AddStringToObject(action, "command", a->cli.command); - cJSON_AddStringToObject(action, "var_name", a->cli.var_name); - cJSON_AddNumberToObject(action, "timeout_ms", a->cli.timeout_ms); - break; - - case TS_AUTO_ACT_LOG: - cJSON_AddStringToObject(action, "message", a->log.message); - cJSON_AddNumberToObject(action, "level", a->log.level); - break; - - case TS_AUTO_ACT_SET_VAR: - cJSON_AddStringToObject(action, "variable", a->set_var.variable); - cJSON_AddItemToObject(action, "value", value_to_json(&a->set_var.value)); - break; - - case TS_AUTO_ACT_WEBHOOK: - cJSON_AddStringToObject(action, "url", a->webhook.url); - cJSON_AddStringToObject(action, "method", a->webhook.method); - cJSON_AddStringToObject(action, "body_template", a->webhook.body_template); - break; - - case TS_AUTO_ACT_SSH_CMD_REF: - cJSON_AddStringToObject(action, "cmd_id", a->ssh_ref.cmd_id); - break; - - default: - break; - } - - // 保存 template_id(如果有) - if (a->template_id[0]) { - cJSON_AddStringToObject(action, "template_id", a->template_id); - } - - cJSON_AddItemToArray(actions, action); - } - cJSON_AddItemToObject(root, "actions", actions); - - char *json_str = cJSON_PrintUnformatted(root); - cJSON_Delete(root); - return json_str; -} - -/* Forward declarations for SD card loading */ -static esp_err_t json_to_rule(const char *json_str, ts_auto_rule_t *rule); - -/*===========================================================================*/ -/* SD 卡独立文件操作 */ -/*===========================================================================*/ - -/** - * @brief 确保 rules 目录存在 - */ -static esp_err_t ensure_rules_dir(void) -{ - struct stat st; - - /* 确保 /sdcard/config 存在 */ - if (stat("/sdcard/config", &st) != 0) { - if (mkdir("/sdcard/config", 0755) != 0) { - ESP_LOGE(TAG, "Failed to create /sdcard/config"); - return ESP_FAIL; - } - } - - /* 确保 /sdcard/config/rules 存在 */ - if (stat(RULES_SDCARD_DIR, &st) != 0) { - if (mkdir(RULES_SDCARD_DIR, 0755) != 0) { - ESP_LOGE(TAG, "Failed to create %s", RULES_SDCARD_DIR); - return ESP_FAIL; - } - } - - return ESP_OK; -} - -/** - * @brief 导出单条规则到独立文件 - */ -static esp_err_t export_rule_to_file(const ts_auto_rule_t *rule) -{ - if (!rule || !rule->id[0]) return ESP_ERR_INVALID_ARG; - - char filepath[128]; - snprintf(filepath, sizeof(filepath), "%s/%s.json", RULES_SDCARD_DIR, rule->id); - - char *json = rule_to_json(rule); - if (!json) return ESP_ERR_NO_MEM; - - FILE *fp = fopen(filepath, "w"); - if (!fp) { - free(json); - ESP_LOGE(TAG, "Failed to open file: %s", filepath); - return ESP_FAIL; - } - - fprintf(fp, "%s\n", json); - fclose(fp); - free(json); - - ESP_LOGD(TAG, "Exported rule to %s", filepath); - return ESP_OK; -} - -/** - * @brief 删除单条规则的独立文件 - * @note 备用函数,当前删除操作在 API 层直接实现 - */ -static esp_err_t __attribute__((unused)) delete_rule_file(const char *id) -{ - if (!id || !id[0]) return ESP_ERR_INVALID_ARG; - - char filepath[128]; - snprintf(filepath, sizeof(filepath), "%s/%s.json", RULES_SDCARD_DIR, id); - - if (unlink(filepath) == 0) { - ESP_LOGD(TAG, "Deleted rule file: %s", filepath); - } - - return ESP_OK; -} - -/** - * @brief 从独立文件目录加载所有规则 - * - * 支持 .tscfg 加密配置优先加载 - */ -static esp_err_t load_rules_from_dir(void) -{ +static esp_err_t load_directory(ts_auto_rule_t *rules, int *count, bool *readonly) { DIR *dir = opendir(RULES_SDCARD_DIR); - if (!dir) { - ESP_LOGD(TAG, "Rules directory not found: %s", RULES_SDCARD_DIR); + if (!dir) return ESP_ERR_NOT_FOUND; - } - - int loaded = 0; + esp_err_t e = ESP_OK; struct dirent *entry; - - /* 使用堆分配避免栈溢出 */ - ts_auto_rule_t *rule = heap_caps_malloc(sizeof(ts_auto_rule_t), MALLOC_CAP_SPIRAM); - if (!rule) rule = malloc(sizeof(ts_auto_rule_t)); - if (!rule) { - closedir(dir); - return ESP_ERR_NO_MEM; - } - - while ((entry = readdir(dir)) != NULL) { - /* 跳过非 .json 和非 .tscfg 文件 */ - size_t len = strlen(entry->d_name); - bool is_json = (len >= 6 && strcmp(entry->d_name + len - 5, ".json") == 0); - bool is_tscfg = (len >= 7 && strcmp(entry->d_name + len - 6, ".tscfg") == 0); - - if (!is_json && !is_tscfg) { - continue; - } - - /* 对于 .json 文件,检查是否存在对应的 .tscfg(跳过以使用加密版本) */ - if (is_json) { - char tscfg_name[128]; - snprintf(tscfg_name, sizeof(tscfg_name), "%.*s.tscfg", (int)(len - 5), entry->d_name); - char tscfg_path[192]; - snprintf(tscfg_path, sizeof(tscfg_path), "%s/%s", RULES_SDCARD_DIR, tscfg_name); - struct stat st; - if (stat(tscfg_path, &st) == 0) { - ESP_LOGD(TAG, "Skipping %s (will use .tscfg)", entry->d_name); - continue; /* 跳过 .json,稍后处理 .tscfg */ - } - } - - /* 限制文件名长度避免缓冲区溢出 */ - if (len > 60) { + *count = 0; + while ((entry = readdir(dir))) { + size_t n = strlen(entry->d_name); + bool enc = n > 6 && !strcmp(entry->d_name + n - 6, ".tscfg"); + bool json = n > 5 && !strcmp(entry->d_name + n - 5, ".json"); + if (!enc && !json) continue; + char path[160], id[TS_AUTO_NAME_MAX_LEN]; + size_t idlen = n - (enc ? 6 : 5); + if (idlen >= sizeof(id)) { + e = ESP_ERR_INVALID_SIZE; + break; } - - char filepath[128]; - if (is_tscfg) { - /* .tscfg 文件 - 构建对应的 .json 路径用于 load_with_priority */ - snprintf(filepath, sizeof(filepath), "%s/%.*s.json", - RULES_SDCARD_DIR, (int)(len - 6), entry->d_name); - } else { - snprintf(filepath, sizeof(filepath), "%s/%.60s", RULES_SDCARD_DIR, entry->d_name); + memcpy(id, entry->d_name, idlen); + id[idlen] = 0; + if (!ts_rule_id_valid(id)) { + e = ESP_ERR_INVALID_ARG; + break; } - - /* 使用 .tscfg 优先加载 */ - char *content = NULL; - size_t content_len = 0; - bool used_tscfg = false; - - esp_err_t ret = ts_config_pack_load_with_priority( - filepath, &content, &content_len, &used_tscfg); - - if (ret != ESP_OK) { - continue; + if (json) { + snprintf(path, sizeof(path), RULES_SDCARD_DIR "/%s.tscfg", id); + struct stat st; + if (stat(path, &st) == 0) + continue; } - - /* 解析并添加 */ - memset(rule, 0, sizeof(ts_auto_rule_t)); - if (json_to_rule(content, rule) == ESP_OK && rule->id[0]) { - if (s_rule_ctx.count < s_rule_ctx.capacity) { - memcpy(&s_rule_ctx.rules[s_rule_ctx.count], rule, sizeof(ts_auto_rule_t)); - s_rule_ctx.count++; - loaded++; - ESP_LOGD(TAG, "Loaded rule from file: %s%s", rule->id, - used_tscfg ? " (encrypted)" : ""); - } + if (*count >= s_rule_ctx.capacity) { + e = ESP_ERR_NO_MEM; + break; } - free(content); + snprintf(path, sizeof(path), RULES_SDCARD_DIR "/%s.json", id); + bool encrypted = false; + e = load_one(path, &rules[*count], &encrypted); + if (e != ESP_OK) + break; + readonly[*count] = encrypted || strcmp(id, rules[*count].id) != 0; + ++*count; } - - free(rule); closedir(dir); - - if (loaded > 0) { - ESP_LOGI(TAG, "Loaded %d rules from directory: %s", loaded, RULES_SDCARD_DIR); - return ESP_OK; - } - - return ESP_ERR_NOT_FOUND; + return e == ESP_OK && !*count ? ESP_ERR_NOT_FOUND : e; } - -/** - * @brief 导出所有规则到独立文件目录 - */ -static esp_err_t export_all_rules_to_dir(void) -{ - if (!ts_storage_sd_mounted()) { - ESP_LOGD(TAG, "SD card not mounted, skip export"); - return ESP_ERR_NOT_FOUND; +static esp_err_t load_legacy_file(const char *path, ts_auto_rule_t *rules, int *count) { + char *text = NULL; + size_t len; + bool encrypted; + esp_err_t e = ts_config_pack_load_with_priority(path, &text, &len, &encrypted); + if (e != ESP_OK) + return e; + cJSON *root = cJSON_Parse(text); + free(text); + cJSON *array = cJSON_GetObjectItemCaseSensitive(root, "rules"); + if (!cJSON_IsArray(array) || cJSON_GetArraySize(array) > s_rule_ctx.capacity) { + cJSON_Delete(root); + return ESP_ERR_INVALID_ARG; } - - esp_err_t ret = ensure_rules_dir(); - if (ret != ESP_OK) return ret; - - int exported = 0; - for (int i = 0; i < s_rule_ctx.count; i++) { - if (export_rule_to_file(&s_rule_ctx.rules[i]) == ESP_OK) { - exported++; - } + *count = 0; + const cJSON *j; + cJSON_ArrayForEach(j, array) { + e = ts_rule_decode(j, &rules[*count]); + if (e != ESP_OK) + break; + ++*count; } - - ESP_LOGI(TAG, "Exported %d rules to directory: %s", exported, RULES_SDCARD_DIR); - return ESP_OK; + cJSON_Delete(root); + return e; } - -/** - * @brief 从 JSON 字符串反序列化规则 - */ -static esp_err_t json_to_rule(const char *json_str, ts_auto_rule_t *rule) -{ - if (!json_str || !rule) return ESP_ERR_INVALID_ARG; - - cJSON *root = cJSON_Parse(json_str); - if (!root) return ESP_ERR_INVALID_ARG; - - memset(rule, 0, sizeof(ts_auto_rule_t)); - - // 基本信息 - cJSON *item; - if ((item = cJSON_GetObjectItem(root, "id")) && cJSON_IsString(item)) { - strncpy(rule->id, item->valuestring, sizeof(rule->id) - 1); - } - if ((item = cJSON_GetObjectItem(root, "name")) && cJSON_IsString(item)) { - strncpy(rule->name, item->valuestring, sizeof(rule->name) - 1); - } - if ((item = cJSON_GetObjectItem(root, "icon")) && cJSON_IsString(item)) { - strncpy(rule->icon, item->valuestring, sizeof(rule->icon) - 1); - } - if ((item = cJSON_GetObjectItem(root, "enabled"))) { - rule->enabled = cJSON_IsTrue(item); - } - if ((item = cJSON_GetObjectItem(root, "manual_trigger"))) { - rule->manual_trigger = cJSON_IsTrue(item); +static esp_err_t load_legacy_nvs(ts_auto_rule_t *rules, int *count) { + nvs_handle_t h; + esp_err_t e = nvs_open(NVS_NAMESPACE_RULES, NVS_READONLY, &h); + *count = 0; + if (e == ESP_ERR_NVS_NOT_FOUND) + return ESP_OK; + if (e != ESP_OK) + return e; + uint8_t n = 0; + e = nvs_get_u8(h, NVS_KEY_RULE_COUNT, &n); + if (e == ESP_ERR_NVS_NOT_FOUND) { + nvs_close(h); + return ESP_OK; } - if ((item = cJSON_GetObjectItem(root, "cooldown_ms")) && cJSON_IsNumber(item)) { - rule->cooldown_ms = (uint32_t)item->valueint; + if (e != ESP_OK || n > s_rule_ctx.capacity) { + nvs_close(h); + return ESP_FAIL; } - - // 条件组 - cJSON *conditions = cJSON_GetObjectItem(root, "conditions"); - if (conditions) { - if ((item = cJSON_GetObjectItem(conditions, "logic")) && cJSON_IsString(item)) { - rule->conditions.logic = strcmp(item->valuestring, "or") == 0 ? - TS_AUTO_LOGIC_OR : TS_AUTO_LOGIC_AND; - } - - cJSON *items = cJSON_GetObjectItem(conditions, "items"); - if (items && cJSON_IsArray(items)) { - int count = cJSON_GetArraySize(items); - if (count > 0) { - rule->conditions.conditions = heap_caps_calloc(count, - sizeof(ts_auto_condition_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rule->conditions.conditions) { - rule->conditions.count = count; - - int idx = 0; - cJSON *cond_item; - cJSON_ArrayForEach(cond_item, items) { - ts_auto_condition_t *c = &rule->conditions.conditions[idx]; - - if ((item = cJSON_GetObjectItem(cond_item, "variable")) && cJSON_IsString(item)) { - strncpy(c->variable, item->valuestring, sizeof(c->variable) - 1); - } - if ((item = cJSON_GetObjectItem(cond_item, "operator")) && cJSON_IsString(item)) { - c->op = str_to_operator(item->valuestring); - } - if ((item = cJSON_GetObjectItem(cond_item, "value"))) { - json_to_value(item, &c->value); - } - idx++; - } - } - } + for (unsigned i = 0; i < n; ++i) { + char key[16]; + snprintf(key, sizeof(key), NVS_KEY_RULE_PREFIX "%u", i); + size_t len = 0; + e = nvs_get_str(h, key, NULL, &len); + if (e != ESP_OK || !len || len > 4000) { + e = ESP_FAIL; + break; } - } - - // 动作数组 - cJSON *actions = cJSON_GetObjectItem(root, "actions"); - if (actions && cJSON_IsArray(actions)) { - int count = cJSON_GetArraySize(actions); - if (count > 0) { - rule->actions = heap_caps_calloc(count, sizeof(ts_auto_action_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rule->actions) { - rule->action_count = count; - - int idx = 0; - cJSON *act_item; - cJSON_ArrayForEach(act_item, actions) { - ts_auto_action_t *a = &rule->actions[idx]; - - if ((item = cJSON_GetObjectItem(act_item, "type")) && cJSON_IsString(item)) { - a->type = str_to_action_type(item->valuestring); - } - if ((item = cJSON_GetObjectItem(act_item, "delay_ms")) && cJSON_IsNumber(item)) { - a->delay_ms = (uint16_t)item->valueint; - } - - // 根据类型解析特定字段 - switch (a->type) { - case TS_AUTO_ACT_LED: - if ((item = cJSON_GetObjectItem(act_item, "device")) && cJSON_IsString(item)) { - strncpy(a->led.device, item->valuestring, sizeof(a->led.device) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "index")) && cJSON_IsNumber(item)) { - a->led.index = (uint8_t)item->valueint; - } - if ((item = cJSON_GetObjectItem(act_item, "r")) && cJSON_IsNumber(item)) { - a->led.r = (uint8_t)item->valueint; - } - if ((item = cJSON_GetObjectItem(act_item, "g")) && cJSON_IsNumber(item)) { - a->led.g = (uint8_t)item->valueint; - } - if ((item = cJSON_GetObjectItem(act_item, "b")) && cJSON_IsNumber(item)) { - a->led.b = (uint8_t)item->valueint; - } - if ((item = cJSON_GetObjectItem(act_item, "effect")) && cJSON_IsString(item)) { - strncpy(a->led.effect, item->valuestring, sizeof(a->led.effect) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "duration_ms")) && cJSON_IsNumber(item)) { - a->led.duration_ms = (uint16_t)item->valueint; - } - break; - - case TS_AUTO_ACT_GPIO: - if ((item = cJSON_GetObjectItem(act_item, "pin")) && cJSON_IsNumber(item)) { - a->gpio.pin = (uint8_t)item->valueint; - } - if ((item = cJSON_GetObjectItem(act_item, "level"))) { - a->gpio.level = cJSON_IsTrue(item); - } - if ((item = cJSON_GetObjectItem(act_item, "pulse_ms")) && cJSON_IsNumber(item)) { - a->gpio.pulse_ms = (uint32_t)item->valueint; - } - break; - - case TS_AUTO_ACT_DEVICE_CTRL: - if ((item = cJSON_GetObjectItem(act_item, "device")) && cJSON_IsString(item)) { - strncpy(a->device.device, item->valuestring, sizeof(a->device.device) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "action")) && cJSON_IsString(item)) { - strncpy(a->device.action, item->valuestring, sizeof(a->device.action) - 1); - } - break; - - case TS_AUTO_ACT_CLI: - if ((item = cJSON_GetObjectItem(act_item, "command")) && cJSON_IsString(item)) { - strncpy(a->cli.command, item->valuestring, sizeof(a->cli.command) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "var_name")) && cJSON_IsString(item)) { - strncpy(a->cli.var_name, item->valuestring, sizeof(a->cli.var_name) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "timeout_ms")) && cJSON_IsNumber(item)) { - a->cli.timeout_ms = (uint32_t)item->valueint; - } - break; - - case TS_AUTO_ACT_LOG: - if ((item = cJSON_GetObjectItem(act_item, "message")) && cJSON_IsString(item)) { - strncpy(a->log.message, item->valuestring, sizeof(a->log.message) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "level")) && cJSON_IsNumber(item)) { - a->log.level = (uint8_t)item->valueint; - } - break; - - case TS_AUTO_ACT_SET_VAR: - if ((item = cJSON_GetObjectItem(act_item, "variable")) && cJSON_IsString(item)) { - strncpy(a->set_var.variable, item->valuestring, sizeof(a->set_var.variable) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "value"))) { - json_to_value(item, &a->set_var.value); - } - break; - - case TS_AUTO_ACT_WEBHOOK: - if ((item = cJSON_GetObjectItem(act_item, "url")) && cJSON_IsString(item)) { - strncpy(a->webhook.url, item->valuestring, sizeof(a->webhook.url) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "method")) && cJSON_IsString(item)) { - strncpy(a->webhook.method, item->valuestring, sizeof(a->webhook.method) - 1); - } - if ((item = cJSON_GetObjectItem(act_item, "body_template")) && cJSON_IsString(item)) { - strncpy(a->webhook.body_template, item->valuestring, sizeof(a->webhook.body_template) - 1); - } - break; - - case TS_AUTO_ACT_SSH_CMD_REF: - if ((item = cJSON_GetObjectItem(act_item, "cmd_id")) && cJSON_IsString(item)) { - strncpy(a->ssh_ref.cmd_id, item->valuestring, sizeof(a->ssh_ref.cmd_id) - 1); - } - break; - - default: - break; - } - - // 加载 template_id(如果有) - if ((item = cJSON_GetObjectItem(act_item, "template_id")) && cJSON_IsString(item)) { - strncpy(a->template_id, item->valuestring, sizeof(a->template_id) - 1); - } - - idx++; - } - } + char *text = heap_caps_malloc(len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!text) { + e = ESP_ERR_NO_MEM; + break; } + e = nvs_get_str(h, key, text, &len); + if (e == ESP_OK) + e = decode_text(text, &rules[*count]); + free(text); + if (e != ESP_OK) + break; + ++*count; } - - cJSON_Delete(root); - return ESP_OK; + nvs_close(h); + return e; } - -/** - * @brief 保存所有规则到 NVS 和 SD 卡 - */ -esp_err_t ts_rules_save(void) -{ - if (!s_rule_ctx.initialized) { +static esp_err_t load_rules(const char *file) { + if (!s_rule_ctx.initialized) return ESP_ERR_INVALID_STATE; - } - - nvs_handle_t handle; - esp_err_t ret = nvs_open(NVS_NAMESPACE_RULES, NVS_READWRITE, &handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to open NVS for rules: %s", esp_err_to_name(ret)); - return ret; - } - - // 先清除旧数据 - nvs_erase_all(handle); - + xSemaphoreTakeRecursive(s_rule_ctx.transaction, portMAX_DELAY); xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - - // 保存数量 - ret = nvs_set_u8(handle, NVS_KEY_RULE_COUNT, (uint8_t)s_rule_ctx.count); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to save rule count: %s", esp_err_to_name(ret)); + bool busy = s_rule_ctx.retired != 0; + for (int i = 0; i < s_rule_ctx.count; ++i) + busy |= ((rule_payload_t *)s_rule_ctx.rules[i].lease)->refs != 0 || + s_rule_ctx.meta[i].executing; + if (busy) { xSemaphoreGive(s_rule_ctx.mutex); - nvs_close(handle); - return ret; - } - - // 保存每条规则到 NVS - for (int i = 0; i < s_rule_ctx.count; i++) { - char key[16]; - snprintf(key, sizeof(key), "%s%d", NVS_KEY_RULE_PREFIX, i); - - char *json = rule_to_json(&s_rule_ctx.rules[i]); - if (!json) { - ESP_LOGW(TAG, "Failed to serialize rule %d", i); - continue; - } - - // 保存到 NVS - ret = nvs_set_str(handle, key, json); - free(json); - - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to save rule %d: %s", i, esp_err_to_name(ret)); - } - } - - xSemaphoreGive(s_rule_ctx.mutex); - - ret = nvs_commit(handle); - nvs_close(handle); - - // 同时导出到 SD 卡独立文件目录 - if (ts_storage_sd_mounted()) { - export_all_rules_to_dir(); - } - - ESP_LOGI(TAG, "Saved %d rules to NVS and SD card", s_rule_ctx.count); - return ret; -} - -/** - * @brief 从存储加载所有规则 - * - * Priority: SD card directory > SD card single file > NVS > empty - * 当从 NVS 加载后,自动导出到 SD 卡(如果 SD 卡已挂载) - */ -esp_err_t ts_rules_load(void) -{ - if (!s_rule_ctx.initialized) { + xSemaphoreGiveRecursive(s_rule_ctx.transaction); return ESP_ERR_INVALID_STATE; } - - esp_err_t ret; - bool loaded_from_sdcard = false; - - /* 1. 优先从 SD 卡独立文件目录加载 */ - if (ts_storage_sd_mounted()) { - ret = load_rules_from_dir(); - if (ret == ESP_OK && s_rule_ctx.count > 0) { - ESP_LOGI(TAG, "Loaded %d rules from SD card directory", s_rule_ctx.count); - loaded_from_sdcard = true; - goto save_to_nvs; - } - - /* 2. 尝试从单一文件加载(兼容旧格式) */ - ret = ts_rules_load_from_file("/sdcard/config/rules.json"); - if (ret == ESP_OK && s_rule_ctx.count > 0) { - ESP_LOGI(TAG, "Loaded %d rules from SD card file", s_rule_ctx.count); - loaded_from_sdcard = true; - /* 迁移到独立文件格式 */ - export_all_rules_to_dir(); - goto save_to_nvs; + s_rule_ctx.loaded = false; + xSemaphoreGive(s_rule_ctx.mutex); + ts_auto_rule_t *rules = + heap_caps_calloc(s_rule_ctx.capacity, sizeof(*rules), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + bool readonly[CONFIG_TS_AUTOMATION_MAX_RULES] = {0}; + int count = 0, source = TS_RULE_SOURCE_NVS; + esp_err_t e = rules ? ESP_OK : ESP_ERR_NO_MEM; + bool staging = false, require_sd = false; + if (e == ESP_OK) + e = ts_rule_store_recover(ts_storage_sd_mounted(), &staging, &require_sd); + if (e == ESP_OK) { + if (file) { + source = TS_RULE_SOURCE_READONLY; + e = load_legacy_file(file, rules, &count); + } else if (staging) { + e = ts_rule_store_load_bank(rules, s_rule_ctx.capacity, &count); + source = require_sd ? TS_RULE_SOURCE_READONLY : TS_RULE_SOURCE_NVS; + } else { + e = ESP_ERR_NOT_FOUND; + if (ts_storage_sd_mounted()) { + e = load_directory(rules, &count, readonly); + if (e == ESP_OK || require_sd) + source = TS_RULE_SOURCE_SD; + if (e == ESP_ERR_NOT_FOUND && !require_sd) { + e = load_legacy_file("/sdcard/config/rules.json", rules, &count); + if (e == ESP_OK) + source = TS_RULE_SOURCE_READONLY; + } + } + if (e == ESP_ERR_NOT_FOUND && !require_sd) + e = load_legacy_nvs(rules, &count); + else if (e == ESP_ERR_NOT_FOUND && + require_sd) { /* Committed empty SD directory remains authoritative. */ + DIR *d = opendir(RULES_SDCARD_DIR); + if (d) { + closedir(d); + e = ESP_OK; + } + } } } - - /* 3. SD 卡无配置,从 NVS 加载 */ - uint8_t count = 0; - nvs_handle_t handle; - ret = nvs_open(NVS_NAMESPACE_RULES, NVS_READONLY, &handle); - - if (ret != ESP_OK) { - ESP_LOGI(TAG, "No saved rules found"); - return ESP_OK; - } - - ret = nvs_get_u8(handle, NVS_KEY_RULE_COUNT, &count); - if (ret != ESP_OK || count == 0) { - nvs_close(handle); - ESP_LOGI(TAG, "No saved rules found"); - return ESP_OK; - } - - ESP_LOGI(TAG, "Loading %d rules from NVS", count); - - /* 使用堆分配避免栈溢出 */ - ts_auto_rule_t *rule = heap_caps_malloc(sizeof(ts_auto_rule_t), MALLOC_CAP_SPIRAM); - if (!rule) rule = malloc(sizeof(ts_auto_rule_t)); - if (!rule) { - nvs_close(handle); - ESP_LOGE(TAG, "Failed to allocate rule buffer"); - return ESP_ERR_NO_MEM; - } - - // 加载每条规则 - for (int i = 0; i < count && s_rule_ctx.count < s_rule_ctx.capacity; i++) { - char key[16]; - snprintf(key, sizeof(key), "%s%d", NVS_KEY_RULE_PREFIX, i); - - // 获取字符串长度 - size_t len = 0; - ret = nvs_get_str(handle, key, NULL, &len); - if (ret != ESP_OK || len == 0) { - continue; - } - - char *json = heap_caps_malloc(len, MALLOC_CAP_SPIRAM); - if (!json) json = malloc(len); - if (!json) { - ESP_LOGW(TAG, "Failed to allocate memory for rule %d", i); - continue; - } - - ret = nvs_get_str(handle, key, json, &len); - if (ret == ESP_OK) { - if (json_to_rule(json, rule) == ESP_OK) { - // 直接添加到数组(不调用 ts_rule_register 避免重复保存) - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - memcpy(&s_rule_ctx.rules[s_rule_ctx.count], rule, sizeof(ts_auto_rule_t)); - s_rule_ctx.count++; - xSemaphoreGive(s_rule_ctx.mutex); - ESP_LOGD(TAG, "Loaded rule: %s", rule->id); + if (e == ESP_OK) + for (int i = 0; i < count; ++i) { + for (int k = 0; k < i; ++k) + if (!strcmp(rules[k].id, rules[i].id)) { + e = ESP_ERR_INVALID_ARG; + break; + } + if (e != ESP_OK) + break; + ts_rule_resolve_presentation(&rules[i]); + if (!rules[i].revision) + rules[i].revision = 1; + if (!payload_adopt(&rules[i])) { + e = ESP_ERR_NO_MEM; + break; } + rules[i].instance = ++s_rule_ctx.next_instance; } - - free(json); - } - - free(rule); - nvs_close(handle); - ESP_LOGI(TAG, "Loaded %d rules from NVS", s_rule_ctx.count); - - /* 从 NVS 加载后,导出到 SD 卡(如果 SD 卡已挂载且有数据) */ - if (s_rule_ctx.count > 0 && ts_storage_sd_mounted()) { - ESP_LOGI(TAG, "Exporting NVS rules to SD card..."); - export_all_rules_to_dir(); - } - - return ESP_OK; - -save_to_nvs: - /* 从 SD 卡加载后,保存到 NVS */ - if (loaded_from_sdcard && s_rule_ctx.count > 0) { - ts_rules_save(); - } - return ESP_OK; -} - -/** - * @brief Load rules from SD card JSON file - * - * 支持 .tscfg 加密配置优先加载 - */ -esp_err_t ts_rules_load_from_file(const char *filepath) -{ - if (!s_rule_ctx.initialized || !filepath) return ESP_ERR_INVALID_ARG; - - /* 使用 .tscfg 优先加载 */ - char *content = NULL; - size_t content_len = 0; - bool used_tscfg = false; - - esp_err_t ret = ts_config_pack_load_with_priority( - filepath, &content, &content_len, &used_tscfg); - - if (ret != ESP_OK) { - ESP_LOGD(TAG, "Cannot open file: %s", filepath); - return ret; - } - - if (used_tscfg) { - ESP_LOGI(TAG, "Loaded encrypted rules from .tscfg"); - } - - cJSON *root = cJSON_Parse(content); - free(content); - - if (!root) { - ESP_LOGW(TAG, "Failed to parse JSON: %s", filepath); - return ESP_ERR_INVALID_ARG; - } - - cJSON *rules = cJSON_GetObjectItem(root, "rules"); - if (!rules || !cJSON_IsArray(rules)) { - cJSON_Delete(root); - ESP_LOGW(TAG, "No 'rules' array in file"); - return ESP_ERR_INVALID_ARG; - } - - int loaded = 0; - - /* 使用堆分配避免栈溢出 */ - ts_auto_rule_t *rule = heap_caps_malloc(sizeof(ts_auto_rule_t), MALLOC_CAP_SPIRAM); - if (!rule) rule = malloc(sizeof(ts_auto_rule_t)); - if (!rule) { - cJSON_Delete(root); - ESP_LOGE(TAG, "Failed to allocate rule buffer"); - return ESP_ERR_NO_MEM; - } - - cJSON *item; - cJSON_ArrayForEach(item, rules) { - if (s_rule_ctx.count >= s_rule_ctx.capacity) break; - - char *json_str = cJSON_PrintUnformatted(item); - if (!json_str) continue; - - if (json_to_rule(json_str, rule) == ESP_OK) { - xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); - memcpy(&s_rule_ctx.rules[s_rule_ctx.count], rule, sizeof(ts_auto_rule_t)); - s_rule_ctx.count++; - xSemaphoreGive(s_rule_ctx.mutex); - loaded++; + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + if (e == ESP_OK) { + ts_auto_rule_t *old = s_rule_ctx.rules; + int oldcount = s_rule_ctx.count; + s_rule_ctx.rules = rules; + s_rule_ctx.count = count; + s_rule_ctx.source = source; + memset(s_rule_ctx.meta, 0, sizeof(s_rule_ctx.meta)); + for (int i = 0; i < count; ++i) + s_rule_ctx.meta[i].readonly = readonly[i]; + s_rule_ctx.loaded = true; + s_rule_ctx.recovery_error = false; + xSemaphoreGive(s_rule_ctx.mutex); + for (int i = 0; i < oldcount; ++i) + payload_free(old[i].lease); + free(old); + } else { + s_rule_ctx.recovery_error = true; + xSemaphoreGive(s_rule_ctx.mutex); + for (int i = 0; i < count; ++i) { + if (rules[i].lease) + payload_free(rules[i].lease); + else + ts_rule_dispose(&rules[i]); } - cJSON_free(json_str); + free(rules); } + xSemaphoreGiveRecursive(s_rule_ctx.transaction); + return e; +} +esp_err_t ts_rules_load(void) { return load_rules(NULL); } +esp_err_t ts_rules_load_from_file(const char *path) { + return path ? load_rules(path) : ESP_ERR_INVALID_ARG; +} +/* Mutations persist through ts_rule_commit; reads/loads never rewrite all rules. */ +esp_err_t ts_rules_save(void) { + return s_rule_ctx.loaded && !s_rule_ctx.recovery_error ? ESP_OK : ESP_ERR_INVALID_STATE; +} - free(rule); - - if (loaded > 0) { - ESP_LOGI(TAG, "Loaded %d rules from SD card: %s", loaded, filepath); - ts_rules_save(); /* Save to NVS for next boot */ +bool ts_rule_edit_begin(void) { + return s_rule_ctx.initialized && xSemaphoreTakeRecursive(s_rule_ctx.transaction, 0) == pdTRUE; +} +void ts_rule_edit_end(void) { xSemaphoreGiveRecursive(s_rule_ctx.transaction); } +void ts_rule_config_status(bool *loaded, bool *recovery) { + if (!s_rule_ctx.initialized) { + *loaded = false; + *recovery = false; + return; } - - return ESP_OK; + xSemaphoreTake(s_rule_ctx.mutex, portMAX_DELAY); + *loaded = s_rule_ctx.loaded; + *recovery = s_rule_ctx.recovery_error; + xSemaphoreGive(s_rule_ctx.mutex); } diff --git a/components/ts_automation/src/ts_rule_store.c b/components/ts_automation/src/ts_rule_store.c new file mode 100644 index 0000000..d31691a --- /dev/null +++ b/components/ts_automation/src/ts_rule_store.c @@ -0,0 +1,400 @@ +#include "ts_rule_store.h" +#include "esp_heap_caps.h" +#include "nvs.h" +#include +#include +#include +#include +#include +#include +#ifndef DIR_RULES +#define DIR_RULES "/sdcard/config/rules" +#endif +#define MAGIC 0x52554c32u +#define NS "rule_stage" +typedef struct { + uint32_t magic, sequence, phase, source, bank, mirror, old_hash, new_hash; + uint8_t had_old, deleting; + char id[TS_AUTO_NAME_MAX_LEN]; +} guard_t; +typedef struct { + uint32_t count, hash; +} bank_meta_t; +static guard_t guard; +static bool recovery_error; +static uint32_t hash_bytes(uint32_t h, const void *data, size_t n) { + const unsigned char *p = data; + while (n--) + h = (h ^ *p++) * 16777619u; + return h; +} +static uint32_t hash_text(const char *s) { return hash_bytes(2166136261u, s, strlen(s)); } +static esp_err_t guard_read(guard_t *g) { + nvs_handle_t h; + esp_err_t e = nvs_open(NS, NVS_READONLY, &h); + if (e != ESP_OK) + return e; + size_t n = sizeof(*g); + e = nvs_get_blob(h, "guard", g, &n); + nvs_close(h); + return e == ESP_OK && n != sizeof(*g) ? ESP_ERR_INVALID_SIZE : e; +} +/* Readback is authoritative even if a commit call reports an uncertain outcome. */ +static esp_err_t guard_write(const guard_t *g) { + nvs_handle_t h; + esp_err_t e = nvs_open(NS, NVS_READWRITE, &h); + if (e != ESP_OK) + return e; + e = nvs_set_blob(h, "guard", g, sizeof(*g)); + if (e == ESP_OK) + e = nvs_commit(h); + nvs_close(h); + guard_t actual = {0}; + esp_err_t read = guard_read(&actual); + if (read == ESP_OK && !memcmp(&actual, g, sizeof(*g))) { + guard = *g; + return ESP_OK; + } + return e == ESP_OK ? ESP_FAIL : e; +} +static void paths(const char *id, char *target, char *temp, char *backup) { + snprintf(target, 160, DIR_RULES "/%s.json", id); + snprintf(temp, 160, DIR_RULES "/.%s.pending", id); + snprintf(backup, 160, DIR_RULES "/.%s.previous", id); +} +static esp_err_t file_hash(const char *path, uint32_t *hash) { + FILE *f = fopen(path, "rb"); + if (!f) + return errno == ENOENT ? ESP_ERR_NOT_FOUND : ESP_FAIL; + char buf[256]; + size_t n; + uint32_t h = 2166136261u; + while ((n = fread(buf, 1, sizeof(buf), f))) + h = hash_bytes(h, buf, n); + bool ok = !ferror(f); + if (fclose(f)) + ok = false; + if (!ok) + return ESP_FAIL; + *hash = h; + return ESP_OK; +} +static bool matches(const char *path, uint32_t expected) { + uint32_t hash; + return file_hash(path, &hash) == ESP_OK && hash == expected; +} +static esp_err_t remove_if_present(const char *path) { + return unlink(path) == 0 || errno == ENOENT ? ESP_OK : ESP_FAIL; +} +static esp_err_t write_file(const char *path, const char *text) { + FILE *f = fopen(path, "wb"); + if (!f) + return ESP_FAIL; + size_t len = strlen(text); + bool ok = fwrite(text, 1, len, f) == len; + if (fflush(f)) + ok = false; + if (fsync(fileno(f))) + ok = false; + if (fclose(f)) + ok = false; + return ok ? ESP_OK : ESP_FAIL; +} +static esp_err_t rollback_sd(const guard_t *g) { + char target[160], temp[160], bak[160]; + paths(g->id, target, temp, bak); + if (g->had_old) { + if (!matches(target, g->old_hash)) { + if (!matches(bak, g->old_hash)) + return ESP_FAIL; + if (remove_if_present(target) != ESP_OK || rename(bak, target)) + return ESP_FAIL; + } + if (!matches(target, g->old_hash)) + return ESP_FAIL; + } else if (remove_if_present(target) != ESP_OK) + return ESP_FAIL; + if (remove_if_present(temp) != ESP_OK) + return ESP_FAIL; + guard_t clean = *g; + clean.phase = 0; + clean.mirror = 0; + return guard_write(&clean); +} +static esp_err_t finish_sd(const guard_t *g) { + char target[160], temp[160], bak[160]; + paths(g->id, target, temp, bak); + if (g->deleting) { + uint32_t unused; + if (file_hash(target, &unused) != ESP_ERR_NOT_FOUND) + return ESP_FAIL; + } else if (!matches(target, g->new_hash)) + return ESP_FAIL; + /* Keep a committed journal until the mirror is known current. */ + if (remove_if_present(temp) != ESP_OK || remove_if_present(bak) != ESP_OK) + return ESP_FAIL; + return ESP_OK; +} +esp_err_t ts_rule_store_recover(bool sd, bool *staging, bool *require_sd) { + *staging = false; + *require_sd = false; + recovery_error = false; + memset(&guard, 0, sizeof(guard)); + esp_err_t e = guard_read(&guard); + if (e == ESP_ERR_NVS_NOT_FOUND) { + memset(&guard, 0, sizeof(guard)); + return ESP_OK; + } + if (e != ESP_OK) + goto bad; + if (guard.magic != MAGIC || guard.bank > 1 || guard.phase > 2 || guard.source > 1) + goto bad; + if (guard.source == TS_RULE_SOURCE_SD) { + *require_sd = true; + if (!sd) { + if (guard.phase == 0 && guard.mirror) { + *staging = true; + return ESP_OK; + } + goto bad; + } + if (guard.phase == 1) { + if (!ts_rule_id_valid(guard.id) || rollback_sd(&guard) != ESP_OK) + goto bad; + } else if (guard.phase == 2) { + if (!ts_rule_id_valid(guard.id) || finish_sd(&guard) != ESP_OK) + goto bad; + } + } else + *staging = true; + return ESP_OK; +bad: + recovery_error = true; + return ESP_ERR_INVALID_STATE; +} +static char *bank_json(nvs_handle_t h, unsigned bank, unsigned i) { + char key[16]; + snprintf(key, sizeof(key), "%c%u", bank ? 'b' : 'a', i); + size_t n = 0; + if (nvs_get_blob(h, key, NULL, &n) != ESP_OK || n < 2 || n > 262144) + return NULL; + char *s = heap_caps_malloc(n, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!s) + return NULL; + if (nvs_get_blob(h, key, s, &n) != ESP_OK || s[n - 1] != 0 || strlen(s) != n - 1) { + free(s); + return NULL; + } + return s; +} +esp_err_t ts_rule_store_load_bank(ts_auto_rule_t *rules, int capacity, int *count) { + nvs_handle_t h; + esp_err_t e = nvs_open(NS, NVS_READONLY, &h); + if (e != ESP_OK) + return e; + bank_meta_t meta; + size_t n = sizeof(meta); + e = nvs_get_blob(h, guard.bank ? "meta_b" : "meta_a", &meta, &n); + if (e != ESP_OK || n != sizeof(meta) || meta.count > (unsigned)capacity) { + nvs_close(h); + return ESP_FAIL; + } + uint32_t hash = 2166136261u; + *count = 0; + for (unsigned i = 0; i < meta.count; ++i) { + char *s = bank_json(h, guard.bank, i); + if (!s) { + e = ESP_FAIL; + break; + } + hash = hash_bytes(hash, s, strlen(s) + 1); + cJSON *j = cJSON_Parse(s); + free(s); + e = ts_rule_decode(j, &rules[i]); + cJSON_Delete(j); + if (e != ESP_OK) + break; + for (unsigned k = 0; k < i; ++k) + if (!strcmp(rules[i].id, rules[k].id)) + e = ESP_ERR_INVALID_ARG; + ++*count; + if (e != ESP_OK) + break; + } + nvs_close(h); + if (e == ESP_OK && hash != meta.hash) + e = ESP_FAIL; + if (e != ESP_OK) { + for (int i = 0; i < *count; ++i) + ts_rule_dispose(&rules[i]); + *count = 0; + } + return e; +} +static esp_err_t stage_bank(const ts_auto_rule_t *rules, int count, const ts_auto_rule_t *candidate, + const char *id, unsigned bank) { + nvs_handle_t h; + esp_err_t e = nvs_open(NS, NVS_READWRITE, &h); + if (e != ESP_OK) + return e; + bank_meta_t meta = {.hash = 2166136261u}; + bool replaced = false; + for (int i = 0; i <= count; ++i) { + const ts_auto_rule_t *r = i < count ? &rules[i] : NULL; + if (r && !strcmp(r->id, id)) { + r = candidate; + replaced = true; + } else if (i == count && !replaced) + r = candidate; + if (!r) + continue; + cJSON *j = ts_rule_encode(r); + char *s = j ? cJSON_PrintUnformatted(j) : NULL; + cJSON_Delete(j); + if (!s) { + e = ESP_ERR_NO_MEM; + break; + } + char key[16]; + snprintf(key, sizeof(key), "%c%u", bank ? 'b' : 'a', (unsigned)meta.count); + e = nvs_set_blob(h, key, s, strlen(s) + 1); + if (e == ESP_OK) { + meta.hash = hash_bytes(meta.hash, s, strlen(s) + 1); + ++meta.count; + } + free(s); + if (e != ESP_OK) + break; + } + if (e == ESP_OK) + e = nvs_set_blob(h, bank ? "meta_b" : "meta_a", &meta, sizeof(meta)); + if (e == ESP_OK) + e = nvs_commit(h); + if (e == ESP_OK) { + bank_meta_t readback; + size_t size = sizeof(readback); + if (nvs_get_blob(h, bank ? "meta_b" : "meta_a", &readback, &size) != ESP_OK || + size != sizeof(readback) || memcmp(&readback, &meta, size)) + e = ESP_FAIL; + } + if (e == ESP_OK) { + uint32_t hash = 2166136261u; + for (unsigned i = 0; i < meta.count; ++i) { + char *s = bank_json(h, bank, i); + if (!s) { + e = ESP_FAIL; + break; + } + hash = hash_bytes(hash, s, strlen(s) + 1); + free(s); + } + if (hash != meta.hash) + e = ESP_FAIL; + } + nvs_close(h); + return e; +} +esp_err_t ts_rule_store_commit(const ts_auto_rule_t *rules, int count, + const ts_auto_rule_t *candidate, const char *id, int source, + ts_rule_commit_t *r) { + *r = (ts_rule_commit_t){ + .applied = 0, .durable = 0, .mirror_synced = 0, .error_code = "storage_failed"}; + if (recovery_error) { + r->error_code = "recovery_required"; + return ESP_ERR_INVALID_STATE; + } + if (source == TS_RULE_SOURCE_READONLY) { + r->error_code = "source_read_only"; + return ESP_ERR_NOT_SUPPORTED; + } + guard_t next = guard; + next.magic = MAGIC; + next.sequence++; + next.source = source; + unsigned bank = guard.magic ? 1 - guard.bank : 0; + if (source == TS_RULE_SOURCE_NVS) { + esp_err_t e = stage_bank(rules, count, candidate, id, bank); + if (e != ESP_OK) + return e; + next.bank = bank; + next.phase = 0; + next.mirror = 1; + if (guard_write(&next) != ESP_OK) { + guard_t actual; + if (guard_read(&actual) != ESP_OK || memcmp(&actual, &guard, sizeof(guard))) { + recovery_error = true; + r->applied = r->durable = -1; + r->error_code = "commit_unknown"; + } + return ESP_FAIL; + } + r->applied = r->durable = r->mirror_synced = 1; + r->error_code = "ok"; + return ESP_OK; + } + char target[160], temp[160], bak[160]; + paths(id, target, temp, bak); + uint32_t oldhash = 0; + esp_err_t prior = file_hash(target, &oldhash); + if (prior != ESP_OK && prior != ESP_ERR_NOT_FOUND) + return prior; + cJSON *j = candidate ? ts_rule_encode(candidate) : NULL; + char *text = j ? cJSON_PrintUnformatted(j) : NULL; + cJSON_Delete(j); + if (candidate && !text) + return ESP_ERR_NO_MEM; + next.phase = 1; + next.mirror = 0; + next.had_old = prior == ESP_OK; + next.old_hash = oldhash; + next.new_hash = text ? hash_text(text) : 0; + next.deleting = !candidate; + strcpy(next.id, id); + /* Persist SD authority before touching it: stale NVS cannot silently reappear. */ + if (guard_write(&next) != ESP_OK) { + free(text); + return ESP_FAIL; + } + bool ok = remove_if_present(temp) == ESP_OK && remove_if_present(bak) == ESP_OK; + if (ok && text) + ok = write_file(temp, text) == ESP_OK && matches(temp, next.new_hash); + free(text); + if (ok && next.had_old) + ok = rename(target, bak) == 0; + if (ok && candidate) + ok = rename(temp, target) == 0; + if (ok) { + next.phase = 2; + ok = guard_write(&next) == ESP_OK; + } + if (!ok) { + if (rollback_sd(&next) != ESP_OK) { + recovery_error = true; + r->applied = r->durable = -1; + r->error_code = "commit_unknown"; + } + return ESP_FAIL; + } + r->applied = r->durable = 1; + r->error_code = "mirror_failed"; + if (stage_bank(rules, count, candidate, id, bank) == ESP_OK) { + next.bank = bank; + next.mirror = 1; + if (guard_write(&next) == ESP_OK) { + r->mirror_synced = 1; + r->error_code = "ok"; + } + } + if (finish_sd(&guard) != ESP_OK) { + r->mirror_synced = 0; + r->error_code = "recovery_cleanup_pending"; + } else if (r->mirror_synced) { + next = guard; + next.phase = 0; + if (guard_write(&next) != ESP_OK) { + r->mirror_synced = 0; + r->error_code = "recovery_cleanup_pending"; + } + } + return ESP_OK; +} diff --git a/components/ts_automation/src/ts_rule_store.h b/components/ts_automation/src/ts_rule_store.h new file mode 100644 index 0000000..9425bbd --- /dev/null +++ b/components/ts_automation/src/ts_rule_store.h @@ -0,0 +1,11 @@ +#pragma once +#include "ts_rule_codec.h" +#define TS_RULE_SOURCE_NVS 0 +#define TS_RULE_SOURCE_SD 1 +#define TS_RULE_SOURCE_READONLY 2 +typedef struct {int applied,durable,mirror_synced;uint32_t revision;const char *error_code;} ts_rule_commit_t; +/* All calls serialized by engine configuration mutex, never evaluation mutex. */ +esp_err_t ts_rule_store_recover(bool sd_mounted, bool *use_staging, bool *require_sd); +esp_err_t ts_rule_store_load_bank(ts_auto_rule_t *rules,int capacity,int *count); +esp_err_t ts_rule_store_commit(const ts_auto_rule_t *rules,int count,const ts_auto_rule_t *candidate, + const char *id,int source,ts_rule_commit_t *result); diff --git a/components/ts_cert/CMakeLists.txt b/components/ts_cert/CMakeLists.txt index d884a97..3f8ea7c 100644 --- a/components/ts_cert/CMakeLists.txt +++ b/components/ts_cert/CMakeLists.txt @@ -3,6 +3,7 @@ idf_component_register( SRCS "src/ts_cert.c" + "src/ts_cert_time.c" INCLUDE_DIRS "include" REQUIRES diff --git a/components/ts_cert/include/ts_cert.h b/components/ts_cert/include/ts_cert.h index 6ad5a84..7d45a26 100644 --- a/components/ts_cert/include/ts_cert.h +++ b/components/ts_cert/include/ts_cert.h @@ -69,21 +69,42 @@ typedef enum { TS_CERT_STATUS_NOT_INITIALIZED = 0, /**< No key pair generated */ TS_CERT_STATUS_KEY_GENERATED, /**< Key pair exists, no CSR yet */ TS_CERT_STATUS_CSR_PENDING, /**< CSR generated, awaiting certificate */ - TS_CERT_STATUS_ACTIVATED, /**< Certificate installed, ready for mTLS */ + TS_CERT_STATUS_ACTIVATED, /**< Certificate time valid; not TLS running */ TS_CERT_STATUS_EXPIRED, /**< Certificate expired */ - TS_CERT_STATUS_ERROR /**< Error state */ + TS_CERT_STATUS_ERROR, /**< Error state */ + TS_CERT_STATUS_TIME_UNVERIFIED, + TS_CERT_STATUS_NOT_YET_VALID } ts_cert_status_t; /** * @brief Certificate information */ +typedef enum { + TS_CERT_VALIDITY_NONE, TS_CERT_VALIDITY_INVALID, TS_CERT_VALIDITY_TIME_UNVERIFIED, + TS_CERT_VALIDITY_NOT_YET_VALID, TS_CERT_VALIDITY_VALID, TS_CERT_VALIDITY_EXPIRED +} ts_cert_validity_t; + +typedef enum { + TS_CERT_OP_OK, TS_CERT_OP_NOT_INITIALIZED, TS_CERT_OP_INVALID_INPUT, + TS_CERT_OP_INPUT_TOO_LARGE, TS_CERT_OP_PEM_PARSE_FAILED, TS_CERT_OP_PRIVATE_KEY_MISSING, + TS_CERT_OP_PRIVATE_KEY_INVALID, TS_CERT_OP_KEY_MISMATCH, TS_CERT_OP_NO_MEMORY, + TS_CERT_OP_STORAGE_FAILED, TS_CERT_OP_CRYPTO_FAILED +} ts_cert_op_error_t; + +/* NVS strings include their terminating NUL; buffer capacities remain unchanged. */ +#define TS_CERT_INSTALL_MAX_LEN 4000 + typedef struct { + ts_cert_validity_t validity; char subject_cn[TS_CERT_DEVICE_ID_MAX_LEN]; /**< Subject Common Name */ char subject_ou[32]; /**< Subject Organizational Unit */ char issuer_cn[TS_CERT_DEVICE_ID_MAX_LEN]; /**< Issuer Common Name */ int64_t not_before; /**< Valid from (Unix timestamp) */ int64_t not_after; /**< Valid until (Unix timestamp) */ - char serial[64]; /**< Serial number (hex) */ + char serial[65]; /**< Serial number (hex) */ + bool serial_truncated; + int64_t seconds_until_expiry; + bool time_ready; bool is_valid; /**< Current validity */ int days_until_expiry; /**< Days until expiration */ } ts_cert_info_t; @@ -109,9 +130,25 @@ typedef struct { bool has_private_key; /**< Private key exists in NVS */ bool has_certificate; /**< Certificate exists in NVS */ bool has_ca_chain; /**< CA chain exists in NVS */ + uint32_t generation; + bool key_valid, key_matches, ca_valid, storage_error, time_ready; ts_cert_info_t cert_info; /**< Certificate details (if exists) */ } ts_cert_pki_status_t; +/* Snapshots own exact-sized buffers. Material lock is never held across TLS calls. */ +typedef struct { + char *key, *certificate, *ca; + uint32_t generation; + char certificate_sha256[65]; +} ts_cert_snapshot_t; +esp_err_t ts_cert_get_snapshot(bool require_ca, ts_cert_snapshot_t *snapshot); +void ts_cert_free_snapshot(ts_cert_snapshot_t *snapshot); +bool ts_cert_prerequisites(const ts_cert_pki_status_t *status, bool require_ca); +const char *ts_cert_validity_to_str(ts_cert_validity_t validity); +esp_err_t ts_cert_install_certificate_ex(const char *pem, size_t len, ts_cert_op_error_t *detail); +esp_err_t ts_cert_install_ca_chain_ex(const char *pem, size_t len, ts_cert_op_error_t *detail); +const char *ts_cert_op_error_to_str(ts_cert_op_error_t detail); + /*===========================================================================*/ /* Initialization */ /*===========================================================================*/ @@ -201,7 +238,7 @@ esp_err_t ts_cert_generate_csr_default(char *csr_pem, size_t *csr_len); * Stores the certificate in NVS after validating it matches the private key. * * @param cert_pem PEM-encoded certificate - * @param cert_len Certificate length + * @param cert_len Actual readable PEM length including one final NUL (not capacity) * @return ESP_OK on success * @return ESP_ERR_INVALID_ARG if certificate is invalid * @return ESP_ERR_INVALID_STATE if certificate doesn't match private key @@ -214,7 +251,7 @@ esp_err_t ts_cert_install_certificate(const char *cert_pem, size_t cert_len); * Stores the CA chain (Intermediate + Root) for verifying peer certificates. * * @param ca_chain_pem PEM-encoded CA chain - * @param ca_chain_len CA chain length + * @param ca_chain_len Actual readable PEM length including one final NUL * @return ESP_OK on success */ esp_err_t ts_cert_install_ca_chain(const char *ca_chain_pem, size_t ca_chain_len); @@ -327,7 +364,7 @@ const char *ts_cert_status_to_str(ts_cert_status_t status); * @brief Parse certificate PEM and extract info * * @param cert_pem PEM-encoded certificate - * @param cert_len Certificate length + * @param cert_len Actual readable PEM length including one final NUL (not capacity) * @param info Output certificate information * @return ESP_OK on success */ diff --git a/components/ts_cert/include/ts_cert_time.h b/components/ts_cert/include/ts_cert_time.h new file mode 100644 index 0000000..f32394c --- /dev/null +++ b/components/ts_cert/include/ts_cert_time.h @@ -0,0 +1,17 @@ +#ifndef TS_CERT_TIME_H +#define TS_CERT_TIME_H +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif +bool ts_cert_time_utc(int year, int month, int day, int hour, int minute, int second, int64_t *out); +int ts_cert_time_days(int64_t seconds); +bool ts_cert_time_ready(int64_t now, int minimum_year); +/* Returns true when the display was truncated. Always terminates if capacity > 0. */ +bool ts_cert_hex(const unsigned char *bytes, size_t length, char *out, size_t capacity); +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/ts_cert/src/ts_cert.c b/components/ts_cert/src/ts_cert.c index 73b5a33..21afc72 100644 --- a/components/ts_cert/src/ts_cert.c +++ b/components/ts_cert/src/ts_cert.c @@ -13,6 +13,12 @@ */ #include "ts_cert.h" +#include "ts_cert_time.h" +#include "ts_event.h" +#include "freertos/semphr.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/sha256.h" +#include #include "ts_crypto.h" #include "ts_core.h" #include "ts_time_sync.h" @@ -38,6 +44,28 @@ #include #include +static esp_err_t ts_cert_init_locked(void); +static void ts_cert_deinit_locked(void); +static esp_err_t ts_cert_generate_keypair_locked(void); +static bool ts_cert_has_keypair_locked(void); +static esp_err_t ts_cert_delete_keypair_locked(void); +static esp_err_t ts_cert_generate_csr_locked(const ts_cert_csr_opts_t *opts, + char *csr_pem, size_t *csr_len); +static esp_err_t ts_cert_generate_csr_default_locked(char *csr_pem, size_t *csr_len); +static esp_err_t ts_cert_install_certificate_ex_locked(const char *pem, size_t len, ts_cert_op_error_t *detail); +static esp_err_t ts_cert_install_ca_chain_ex_locked(const char *pem, size_t len, ts_cert_op_error_t *detail); +static esp_err_t ts_cert_install_certificate_locked(const char *pem, size_t len); +static esp_err_t ts_cert_install_ca_chain_locked(const char *pem, size_t len); +static esp_err_t ts_cert_get_certificate_locked(char *cert_pem, size_t *cert_len); +static esp_err_t ts_cert_get_private_key_locked(char *key_pem, size_t *key_len); +static esp_err_t ts_cert_get_ca_chain_locked(char *ca_chain_pem, size_t *ca_chain_len); +static esp_err_t ts_cert_refresh_status_locked(void); +static esp_err_t ts_cert_get_status_locked(ts_cert_pki_status_t *status); +static esp_err_t ts_cert_get_info_locked(ts_cert_info_t *info); +static bool ts_cert_is_valid_locked(void); +static int ts_cert_days_until_expiry_locked(void); +static esp_err_t ts_cert_factory_reset_locked(void); +static esp_err_t ts_cert_get_snapshot_locked(bool require_ca, ts_cert_snapshot_t *snapshot); static const char *TAG = "ts_cert"; /*===========================================================================*/ @@ -58,6 +86,25 @@ static const char *TAG = "ts_cert"; /* Static Variables */ /*===========================================================================*/ +/* Initialized once during boot, retained across deinit to protect late readers. */ +static StaticSemaphore_t s_mutex_storage; +static SemaphoreHandle_t s_mutex; +static portMUX_TYPE s_mutex_init_lock = portMUX_INITIALIZER_UNLOCKED; +static void material_lock(void) +{ + portENTER_CRITICAL(&s_mutex_init_lock); + if (!s_mutex) s_mutex = xSemaphoreCreateMutexStatic(&s_mutex_storage); + portEXIT_CRITICAL(&s_mutex_init_lock); + xSemaphoreTake(s_mutex, portMAX_DELAY); +} +static uint32_t s_generation = 1, s_metadata_generation; +static ts_cert_info_t s_metadata; +static bool s_key_valid, s_key_matches, s_ca_valid, s_storage_error; +static char s_fingerprint[65]; +static void refresh_metadata(void); +static void evaluate_time(ts_cert_info_t *info, int64_t now); +static esp_err_t info_from_crt(const mbedtls_x509_crt *crt, ts_cert_info_t *info); + static bool s_initialized = false; static nvs_handle_t s_nvs_handle = 0; @@ -76,6 +123,17 @@ static bool s_rng_initialized = false; /* Internal Functions */ /*===========================================================================*/ +/* mbedTLS can combine a high-level error with a low-level allocation error. */ +static bool allocation_error(int error) +{ + if (error >= 0) return false; + int high = (-error) & 0xFF80; + int low = (-error) & 0x007F; + return high == -MBEDTLS_ERR_X509_ALLOC_FAILED || high == -MBEDTLS_ERR_PK_ALLOC_FAILED || + high == -MBEDTLS_ERR_ECP_ALLOC_FAILED || low == -MBEDTLS_ERR_MPI_ALLOC_FAILED || + low == -MBEDTLS_ERR_ASN1_ALLOC_FAILED; +} + static esp_err_t init_rng(void) { if (s_rng_initialized) return ESP_OK; @@ -90,7 +148,9 @@ static esp_err_t init_rng(void) char err_buf[128]; mbedtls_strerror(ret, err_buf, sizeof(err_buf)); ESP_LOGE(TAG, "RNG seed failed: %s", err_buf); - return ESP_FAIL; + mbedtls_ctr_drbg_free(&s_ctr_drbg); + mbedtls_entropy_free(&s_entropy); + return allocation_error(ret) ? ESP_ERR_NO_MEM : ESP_FAIL; } s_rng_initialized = true; @@ -113,43 +173,50 @@ static esp_err_t nvs_read_string(const char *key, char **out_str) } if (!*out_str) return ESP_ERR_NO_MEM; - return nvs_get_str(s_nvs_handle, key, *out_str, &required_size); + err = nvs_get_str(s_nvs_handle, key, *out_str, &required_size); + if (err != ESP_OK) { free(*out_str); *out_str = NULL; } + return err; } static esp_err_t nvs_write_string(const char *key, const char *str) { + const char *stage = "set"; esp_err_t err = nvs_set_str(s_nvs_handle, key, str); - if (err != ESP_OK) return err; - return nvs_commit(s_nvs_handle); + if (err == ESP_OK) { stage = "commit"; err = nvs_commit(s_nvs_handle); } + if (err != ESP_OK) { + s_storage_error = true; /* Persistence uncertain: block future TLS loading. */ + ESP_LOGE(TAG, "NVS %s (%s): %s", stage, key, esp_err_to_name(err)); + } + return err; } -static void update_status(void) +static void set_status(const ts_cert_info_t *current) { - if (s_private_key_pem && s_certificate_pem) { - /* - * Check if certificate is expired - * 但如果系统时间未同步,跳过过期检查(使用统一的 ts_time_sync API) - */ - if (ts_time_sync_needs_sync()) { - /* 时间未同步,假设证书有效(这是正常的启动顺序,NTP 同步在网络就绪后完成) */ - ESP_LOGI(TAG, "Time not synced yet, deferring cert expiry check"); - s_status = TS_CERT_STATUS_ACTIVATED; - } else { - ts_cert_info_t info; - if (ts_cert_get_info(&info) == ESP_OK && info.is_valid) { - s_status = TS_CERT_STATUS_ACTIVATED; - } else { - s_status = TS_CERT_STATUS_EXPIRED; - } + ts_cert_info_t info = *current; + if (s_storage_error || (s_private_key_pem && !s_key_valid) || + (s_certificate_pem && (info.validity == TS_CERT_VALIDITY_INVALID || + (s_private_key_pem && !s_key_matches)))) { + s_status = TS_CERT_STATUS_ERROR; + } else if (s_private_key_pem && s_certificate_pem) { + switch (info.validity) { + case TS_CERT_VALIDITY_TIME_UNVERIFIED: s_status = TS_CERT_STATUS_TIME_UNVERIFIED; break; + case TS_CERT_VALIDITY_NOT_YET_VALID: s_status = TS_CERT_STATUS_NOT_YET_VALID; break; + case TS_CERT_VALIDITY_VALID: s_status = TS_CERT_STATUS_ACTIVATED; break; + case TS_CERT_VALIDITY_EXPIRED: s_status = TS_CERT_STATUS_EXPIRED; break; + default: s_status = TS_CERT_STATUS_ERROR; break; } } else if (s_private_key_pem) { - s_status = TS_CERT_STATUS_KEY_GENERATED; - } else { - s_status = TS_CERT_STATUS_NOT_INITIALIZED; - } - - nvs_set_u8(s_nvs_handle, NVS_KEY_STATUS, (uint8_t)s_status); - nvs_commit(s_nvs_handle); + if (s_status != TS_CERT_STATUS_CSR_PENDING) s_status = TS_CERT_STATUS_KEY_GENERATED; + } else s_status = TS_CERT_STATUS_NOT_INITIALIZED; + /* Derived status never writes NVS. */ +} + +static void update_status(void) +{ + refresh_metadata(); + ts_cert_info_t info = s_metadata; + evaluate_time(&info, (int64_t)time(NULL)); + set_status(&info); } /*===========================================================================*/ @@ -166,7 +233,7 @@ static void update_status(void) * iPAddress [7] OCTET STRING * } */ -static int build_san_extension(const ts_cert_csr_opts_t *opts, +static int build_san_extension(const ts_cert_csr_opts_t *opts, unsigned char *buf, size_t buf_size, size_t *olen) { @@ -224,7 +291,7 @@ static int build_san_extension(const ts_cert_csr_opts_t *opts, /* Public Functions */ /*===========================================================================*/ -esp_err_t ts_cert_init(void) +static esp_err_t ts_cert_init_locked(void) { if (s_initialized) return ESP_OK; @@ -234,29 +301,20 @@ esp_err_t ts_cert_init(void) return err; } - /* Load existing credentials */ err = nvs_read_string(NVS_KEY_PRIVKEY, &s_private_key_pem); - if (err == ESP_OK && s_private_key_pem) { - ESP_LOGI(TAG, "Loaded private key from NVS (%d bytes)", strlen(s_private_key_pem)); - } else if (err != ESP_ERR_NVS_NOT_FOUND) { - ESP_LOGW(TAG, "Failed to read private key: %s", esp_err_to_name(err)); - } - - err = nvs_read_string(NVS_KEY_CERT, &s_certificate_pem); - if (err == ESP_OK && s_certificate_pem) { - ESP_LOGI(TAG, "Loaded certificate from NVS (%d bytes)", strlen(s_certificate_pem)); - } else if (err != ESP_ERR_NVS_NOT_FOUND) { - ESP_LOGW(TAG, "Failed to read certificate: %s", esp_err_to_name(err)); - } - - err = nvs_read_string(NVS_KEY_CA_CHAIN, &s_ca_chain_pem); - if (err == ESP_OK && s_ca_chain_pem) { - ESP_LOGI(TAG, "Loaded CA chain from NVS (%d bytes)", strlen(s_ca_chain_pem)); - } else if (err != ESP_ERR_NVS_NOT_FOUND) { - ESP_LOGW(TAG, "Failed to read CA chain: %s", esp_err_to_name(err)); + if (err == ESP_OK) err = nvs_read_string(NVS_KEY_CERT, &s_certificate_pem); + if (err == ESP_OK) err = nvs_read_string(NVS_KEY_CA_CHAIN, &s_ca_chain_pem); + if (err != ESP_OK) { + if (s_private_key_pem) mbedtls_platform_zeroize(s_private_key_pem, strlen(s_private_key_pem)); + free(s_private_key_pem); free(s_certificate_pem); free(s_ca_chain_pem); + s_private_key_pem = s_certificate_pem = s_ca_chain_pem = NULL; + nvs_close(s_nvs_handle); s_nvs_handle = 0; + s_storage_error = true; + return err; } - - /* 必须先设置 initialized,因为 update_status 会调用 ts_cert_get_info */ + s_storage_error = false; + s_metadata_generation = 0; + /* 必须先设置 initialized,因为 update_status 会调用 ts_cert_get_info_locked */ s_initialized = true; update_status(); @@ -269,10 +327,11 @@ esp_err_t ts_cert_init(void) return ESP_OK; } -void ts_cert_deinit(void) +static void ts_cert_deinit_locked(void) { if (!s_initialized) return; + if (s_private_key_pem) mbedtls_platform_zeroize(s_private_key_pem, strlen(s_private_key_pem)); free(s_private_key_pem); free(s_certificate_pem); free(s_ca_chain_pem); @@ -298,7 +357,7 @@ void ts_cert_deinit(void) /* Key Pair Management */ /*===========================================================================*/ -esp_err_t ts_cert_generate_keypair(void) +static esp_err_t ts_cert_generate_keypair_locked(void) { if (!s_initialized) return ESP_ERR_INVALID_STATE; @@ -331,6 +390,7 @@ esp_err_t ts_cert_generate_keypair(void) if (err != ESP_OK) { ESP_LOGE(TAG, "Key export failed: %s", esp_err_to_name(err)); + mbedtls_platform_zeroize(key_pem, TS_CERT_KEY_MAX_LEN); free(key_pem); return err; } @@ -339,42 +399,55 @@ esp_err_t ts_cert_generate_keypair(void) err = nvs_write_string(NVS_KEY_PRIVKEY, key_pem); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to store key: %s", esp_err_to_name(err)); + mbedtls_platform_zeroize(key_pem, TS_CERT_KEY_MAX_LEN); free(key_pem); return err; } - /* Update cache */ - free(s_private_key_pem); - s_private_key_pem = key_pem; - - /* Clear existing certificate (key changed) */ - nvs_erase_key(s_nvs_handle, NVS_KEY_CERT); - nvs_commit(s_nvs_handle); - free(s_certificate_pem); - s_certificate_pem = NULL; - + err = nvs_erase_key(s_nvs_handle, NVS_KEY_CERT); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + if (err == ESP_OK) err = nvs_commit(s_nvs_handle); + if (err != ESP_OK) { + s_storage_error = true; + mbedtls_platform_zeroize(key_pem, strlen(key_pem)); free(key_pem); + return err; + } + if (s_private_key_pem) mbedtls_platform_zeroize(s_private_key_pem, strlen(s_private_key_pem)); + free(s_private_key_pem); s_private_key_pem = key_pem; + free(s_certificate_pem); s_certificate_pem = NULL; + ++s_generation; + s_status = TS_CERT_STATUS_KEY_GENERATED; update_status(); - + ESP_LOGI(TAG, "Key pair generated and stored"); return ESP_OK; } -bool ts_cert_has_keypair(void) +static bool ts_cert_has_keypair_locked(void) { return s_private_key_pem != NULL; } -esp_err_t ts_cert_delete_keypair(void) +static esp_err_t ts_cert_delete_keypair_locked(void) { if (!s_initialized) return ESP_ERR_INVALID_STATE; - nvs_erase_key(s_nvs_handle, NVS_KEY_PRIVKEY); - nvs_erase_key(s_nvs_handle, NVS_KEY_CERT); - nvs_commit(s_nvs_handle); - + esp_err_t err = ESP_OK; + if (err == ESP_OK) { + err = nvs_erase_key(s_nvs_handle, NVS_KEY_PRIVKEY); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + } + if (err == ESP_OK) { + err = nvs_erase_key(s_nvs_handle, NVS_KEY_CERT); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + } + if (err == ESP_OK) err = nvs_commit(s_nvs_handle); + if (err != ESP_OK) { s_storage_error = true; return err; } + ++s_generation; + /* Securely clear memory */ if (s_private_key_pem) { - memset(s_private_key_pem, 0, strlen(s_private_key_pem)); + mbedtls_platform_zeroize(s_private_key_pem, strlen(s_private_key_pem)); free(s_private_key_pem); s_private_key_pem = NULL; } @@ -392,7 +465,7 @@ esp_err_t ts_cert_delete_keypair(void) /* CSR Generation */ /*===========================================================================*/ -esp_err_t ts_cert_generate_csr(const ts_cert_csr_opts_t *opts, +static esp_err_t ts_cert_generate_csr_locked(const ts_cert_csr_opts_t *opts, char *csr_pem, size_t *csr_len) { if (!s_initialized) return ESP_ERR_INVALID_STATE; @@ -490,8 +563,7 @@ esp_err_t ts_cert_generate_csr(const ts_cert_csr_opts_t *opts, *csr_len = strlen(csr_pem) + 1; s_status = TS_CERT_STATUS_CSR_PENDING; - nvs_set_u8(s_nvs_handle, NVS_KEY_STATUS, (uint8_t)s_status); - nvs_commit(s_nvs_handle); + ESP_LOGI(TAG, "CSR generated for %s", opts->device_id); err = ESP_OK; @@ -502,7 +574,7 @@ esp_err_t ts_cert_generate_csr(const ts_cert_csr_opts_t *opts, return err; } -esp_err_t ts_cert_generate_csr_default(char *csr_pem, size_t *csr_len) +static esp_err_t ts_cert_generate_csr_default_locked(char *csr_pem, size_t *csr_len) { /* Get device IP address */ esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); @@ -531,166 +603,127 @@ esp_err_t ts_cert_generate_csr_default(char *csr_pem, size_t *csr_len) }; opts.ip_sans[0] = ip_addr; - return ts_cert_generate_csr(&opts, csr_pem, csr_len); + return ts_cert_generate_csr_locked(&opts, csr_pem, csr_len); } /*===========================================================================*/ /* Certificate Management */ /*===========================================================================*/ -esp_err_t ts_cert_install_certificate(const char *cert_pem, size_t cert_len) +static char *copy_pem(const char *pem, size_t len) { - if (!s_initialized) return ESP_ERR_INVALID_STATE; - if (!cert_pem || cert_len == 0) return ESP_ERR_INVALID_ARG; - if (!s_private_key_pem) { - ESP_LOGE(TAG, "No private key, cannot install certificate"); - return ESP_ERR_INVALID_STATE; + char *p = heap_caps_malloc(len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!p) p = malloc(len); + if (p) memcpy(p, pem, len); + return p; +} + +static void save_ca_copy(const char *pem) +{ + struct stat st; + if (stat(CA_CHAIN_SDCARD_DIR, &st) != 0 && mkdir(CA_CHAIN_SDCARD_DIR, 0755) != 0) { + ESP_LOGW(TAG, "CA saved in NVS; SD copy unavailable"); return; } - - /* Parse and validate certificate */ + FILE *file = fopen(CA_CHAIN_SDCARD_PATH, "w"); + if (!file) { ESP_LOGW(TAG, "CA saved in NVS; SD copy open failed"); return; } + size_t len = strlen(pem); + size_t written = fwrite(pem, 1, len, file); + int closed = fclose(file); + if (written != len || closed != 0) ESP_LOGW(TAG, "CA saved in NVS; SD copy write failed"); +} + +static esp_err_t install_material(const char *pem, size_t len, bool ca, ts_cert_op_error_t *detail) +{ + ts_cert_op_error_t why = TS_CERT_OP_OK; + esp_err_t err = ESP_ERR_INVALID_ARG; + char *replacement = NULL; mbedtls_x509_crt crt; - mbedtls_x509_crt_init(&crt); - - int ret = mbedtls_x509_crt_parse(&crt, (const unsigned char *)cert_pem, cert_len); - if (ret != 0) { - char err_buf[128]; - mbedtls_strerror(ret, err_buf, sizeof(err_buf)); - ESP_LOGE(TAG, "Failed to parse certificate: %s", err_buf); - mbedtls_x509_crt_free(&crt); - return ESP_ERR_INVALID_ARG; - } - - /* Verify certificate matches private key */ mbedtls_pk_context pk; - mbedtls_pk_init(&pk); - - esp_err_t err = init_rng(); - if (err != ESP_OK) { - mbedtls_x509_crt_free(&crt); - return err; + mbedtls_x509_crt_init(&crt); mbedtls_pk_init(&pk); + if (!s_initialized) { why = TS_CERT_OP_NOT_INITIALIZED; err = ESP_ERR_INVALID_STATE; goto done; } + if (!pem || len <= 1) { why = TS_CERT_OP_INVALID_INPUT; goto done; } + size_t cap = ca ? TS_CERT_CA_CHAIN_MAX_LEN : TS_CERT_PEM_MAX_LEN; + if (cap > TS_CERT_INSTALL_MAX_LEN) cap = TS_CERT_INSTALL_MAX_LEN; + if (len > cap) { why = TS_CERT_OP_INPUT_TOO_LARGE; goto done; } + if (pem[len-1] != 0 || memchr(pem, 0, len-1)) { why = TS_CERT_OP_INVALID_INPUT; goto done; } + size_t i = 0; + while (i < len-1 && isspace((unsigned char)pem[i])) ++i; + if (i == len-1) { why = TS_CERT_OP_INVALID_INPUT; goto done; } + if (!ca && !s_private_key_pem) { + why = TS_CERT_OP_PRIVATE_KEY_MISSING; err = ESP_ERR_INVALID_STATE; goto done; } - - ret = mbedtls_pk_parse_key(&pk, (const unsigned char *)s_private_key_pem, - strlen(s_private_key_pem) + 1, NULL, 0, - mbedtls_ctr_drbg_random, &s_ctr_drbg); + if (s_storage_error) { why = TS_CERT_OP_STORAGE_FAILED; err = ESP_FAIL; goto done; } + char *old = ca ? s_ca_chain_pem : s_certificate_pem; + replacement = copy_pem(pem, len); + if (!replacement) { why = TS_CERT_OP_NO_MEMORY; err = ESP_ERR_NO_MEM; goto done; } + int ret = mbedtls_x509_crt_parse(&crt, (const unsigned char *)pem, len); if (ret != 0) { - ESP_LOGE(TAG, "Failed to parse private key for verification"); - mbedtls_x509_crt_free(&crt); - mbedtls_pk_free(&pk); - return ESP_FAIL; + ESP_LOGW(TAG, "PEM parse: %d", ret); + why = allocation_error(ret) ? TS_CERT_OP_NO_MEMORY : TS_CERT_OP_PEM_PARSE_FAILED; + err = why == TS_CERT_OP_NO_MEMORY ? ESP_ERR_NO_MEM : ESP_ERR_INVALID_ARG; + goto done; } - - /* Check if public keys match */ - unsigned char cert_pub[256], key_pub[256]; - size_t cert_pub_len, key_pub_len; - - ret = mbedtls_pk_write_pubkey_der(&crt.pk, cert_pub, sizeof(cert_pub)); - if (ret < 0) { - ESP_LOGE(TAG, "Failed to extract certificate public key"); - err = ESP_FAIL; - goto verify_cleanup; + if (!ca) { + err = init_rng(); + if (err != ESP_OK) { why = err == ESP_ERR_NO_MEM ? TS_CERT_OP_NO_MEMORY : TS_CERT_OP_CRYPTO_FAILED; goto done; } + ret = mbedtls_pk_parse_key(&pk, (const unsigned char *)s_private_key_pem, + strlen(s_private_key_pem)+1, NULL, 0, mbedtls_ctr_drbg_random, &s_ctr_drbg); + if (ret != 0) { + why = allocation_error(ret) ? TS_CERT_OP_NO_MEMORY : TS_CERT_OP_PRIVATE_KEY_INVALID; + err = why == TS_CERT_OP_NO_MEMORY ? ESP_ERR_NO_MEM : ESP_FAIL; + goto done; + } + ret = mbedtls_pk_check_pair(&crt.pk, &pk, mbedtls_ctr_drbg_random, &s_ctr_drbg); + if (ret != 0) { + why = allocation_error(ret) ? TS_CERT_OP_NO_MEMORY : TS_CERT_OP_KEY_MISMATCH; + err = why == TS_CERT_OP_NO_MEMORY ? ESP_ERR_NO_MEM : ESP_ERR_INVALID_STATE; + goto done; + } } - cert_pub_len = ret; - - ret = mbedtls_pk_write_pubkey_der(&pk, key_pub, sizeof(key_pub)); - if (ret < 0) { - ESP_LOGE(TAG, "Failed to extract private key public component"); - err = ESP_FAIL; - goto verify_cleanup; + /* Reuse the candidate parser for metadata: no second parse or allocation after persistence. */ + ts_cert_info_t info = {0}; + unsigned char hash[32]; + if (!ca) { + info_from_crt(&crt, &info); + ret = mbedtls_sha256(crt.raw.p, crt.raw.len, hash, 0); + if (ret != 0) { why = TS_CERT_OP_CRYPTO_FAILED; err = ESP_FAIL; goto done; } } - key_pub_len = ret; - - /* Public keys are written at the end of the buffer */ - if (cert_pub_len != key_pub_len || - memcmp(cert_pub + sizeof(cert_pub) - cert_pub_len, - key_pub + sizeof(key_pub) - key_pub_len, - cert_pub_len) != 0) { - ESP_LOGE(TAG, "Certificate does not match private key"); - err = ESP_ERR_INVALID_STATE; - goto verify_cleanup; + bool changed = !old || strcmp(old, pem) != 0; + if (changed) { + err = nvs_write_string(ca ? NVS_KEY_CA_CHAIN : NVS_KEY_CERT, pem); + if (err != ESP_OK) { why = TS_CERT_OP_STORAGE_FAILED; goto done; } + if (ca) s_ca_chain_pem = replacement; else s_certificate_pem = replacement; + replacement = NULL; + free(old); + ++s_generation; } - - /* Store certificate */ - err = nvs_write_string(NVS_KEY_CERT, cert_pem); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to store certificate: %s", esp_err_to_name(err)); - goto verify_cleanup; + if (ca) s_ca_valid = true; + else { + s_metadata = info; + s_key_valid = s_key_matches = true; + ts_cert_hex(hash, sizeof(hash), s_fingerprint, sizeof(s_fingerprint)); } - - /* Update cache */ - free(s_certificate_pem); - s_certificate_pem = strdup(cert_pem); - + s_metadata_generation = s_generation; update_status(); - - ESP_LOGI(TAG, "Certificate installed successfully"); + if (ca && changed) save_ca_copy(pem); err = ESP_OK; - -verify_cleanup: - mbedtls_x509_crt_free(&crt); - mbedtls_pk_free(&pk); + done: + free(replacement); + mbedtls_pk_free(&pk); mbedtls_x509_crt_free(&crt); + if (detail) *detail = why; return err; } -esp_err_t ts_cert_install_ca_chain(const char *ca_chain_pem, size_t ca_chain_len) -{ - if (!s_initialized) return ESP_ERR_INVALID_STATE; - if (!ca_chain_pem || ca_chain_len == 0) return ESP_ERR_INVALID_ARG; - - /* Validate CA chain can be parsed */ - mbedtls_x509_crt ca; - mbedtls_x509_crt_init(&ca); - - int ret = mbedtls_x509_crt_parse(&ca, (const unsigned char *)ca_chain_pem, ca_chain_len); - mbedtls_x509_crt_free(&ca); - - if (ret != 0) { - char err_buf[128]; - mbedtls_strerror(ret, err_buf, sizeof(err_buf)); - ESP_LOGE(TAG, "Invalid CA chain: %s", err_buf); - return ESP_ERR_INVALID_ARG; - } - - /* Store CA chain in NVS */ - esp_err_t err = nvs_write_string(NVS_KEY_CA_CHAIN, ca_chain_pem); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to store CA chain: %s", esp_err_to_name(err)); - return err; - } - - /* Update cache */ - free(s_ca_chain_pem); - s_ca_chain_pem = strdup(ca_chain_pem); - - /* Save CA chain to SD card for user download */ - /* Create directory if not exists */ - struct stat st; - if (stat(CA_CHAIN_SDCARD_DIR, &st) != 0) { - if (mkdir(CA_CHAIN_SDCARD_DIR, 0755) != 0) { - ESP_LOGW(TAG, "Failed to create %s directory (SD card may not be mounted)", CA_CHAIN_SDCARD_DIR); - /* Continue anyway, NVS storage succeeded */ - } - } - - /* Write CA chain file */ - FILE *f = fopen(CA_CHAIN_SDCARD_PATH, "w"); - if (f) { - size_t written = fwrite(ca_chain_pem, 1, strlen(ca_chain_pem), f); - fclose(f); - if (written == strlen(ca_chain_pem)) { - ESP_LOGI(TAG, "CA chain saved to %s for user download", CA_CHAIN_SDCARD_PATH); - } else { - ESP_LOGW(TAG, "Partial write to SD card: %zu/%zu bytes", written, strlen(ca_chain_pem)); - } - } else { - ESP_LOGW(TAG, "Could not save CA chain to SD card (SD card may not be mounted)"); - } - - ESP_LOGI(TAG, "CA chain installed"); - return ESP_OK; -} +static esp_err_t ts_cert_install_certificate_ex_locked(const char *pem, size_t len, ts_cert_op_error_t *detail) +{ return install_material(pem, len, false, detail); } +static esp_err_t ts_cert_install_ca_chain_ex_locked(const char *pem, size_t len, ts_cert_op_error_t *detail) +{ return install_material(pem, len, true, detail); } +static esp_err_t ts_cert_install_certificate_locked(const char *pem, size_t len) +{ return ts_cert_install_certificate_ex_locked(pem, len, NULL); } +static esp_err_t ts_cert_install_ca_chain_locked(const char *pem, size_t len) +{ return ts_cert_install_ca_chain_ex_locked(pem, len, NULL); } -esp_err_t ts_cert_get_certificate(char *cert_pem, size_t *cert_len) +static esp_err_t ts_cert_get_certificate_locked(char *cert_pem, size_t *cert_len) { if (!s_initialized) return ESP_ERR_INVALID_STATE; if (!cert_pem || !cert_len) return ESP_ERR_INVALID_ARG; @@ -710,7 +743,7 @@ esp_err_t ts_cert_get_certificate(char *cert_pem, size_t *cert_len) return ESP_OK; } -esp_err_t ts_cert_get_private_key(char *key_pem, size_t *key_len) +static esp_err_t ts_cert_get_private_key_locked(char *key_pem, size_t *key_len) { if (!s_initialized) return ESP_ERR_INVALID_STATE; if (!key_pem || !key_len) return ESP_ERR_INVALID_ARG; @@ -730,7 +763,7 @@ esp_err_t ts_cert_get_private_key(char *key_pem, size_t *key_len) return ESP_OK; } -esp_err_t ts_cert_get_ca_chain(char *ca_chain_pem, size_t *ca_chain_len) +static esp_err_t ts_cert_get_ca_chain_locked(char *ca_chain_pem, size_t *ca_chain_len) { if (!s_initialized) return ESP_ERR_INVALID_STATE; if (!ca_chain_pem || !ca_chain_len) return ESP_ERR_INVALID_ARG; @@ -754,7 +787,7 @@ esp_err_t ts_cert_get_ca_chain(char *ca_chain_pem, size_t *ca_chain_len) /* Status & Info */ /*===========================================================================*/ -esp_err_t ts_cert_refresh_status(void) +static esp_err_t ts_cert_refresh_status_locked(void) { if (!s_initialized) return ESP_ERR_INVALID_STATE; @@ -773,50 +806,57 @@ esp_err_t ts_cert_refresh_status(void) return ESP_OK; } -esp_err_t ts_cert_get_status(ts_cert_pki_status_t *status) +static esp_err_t ts_cert_get_status_locked(ts_cert_pki_status_t *status) { - if (!s_initialized) return ESP_ERR_INVALID_STATE; if (!status) return ESP_ERR_INVALID_ARG; - + memset(status, 0, sizeof(*status)); + if (!s_initialized) return ESP_ERR_INVALID_STATE; + refresh_metadata(); + status->has_private_key = s_private_key_pem != NULL; + status->has_certificate = s_certificate_pem != NULL; + status->has_ca_chain = s_ca_chain_pem != NULL; + status->generation = s_generation; + status->storage_error = s_storage_error; + status->key_valid = s_key_valid; + status->key_matches = s_key_matches; + status->ca_valid = s_ca_valid; + status->cert_info = s_metadata; + int64_t now = (int64_t)time(NULL); + status->time_ready = ts_cert_time_ready(now, TS_TIME_MIN_VALID_YEAR); + evaluate_time(&status->cert_info, now); + set_status(&status->cert_info); status->status = s_status; - status->has_private_key = (s_private_key_pem != NULL); - status->has_certificate = (s_certificate_pem != NULL); - status->has_ca_chain = (s_ca_chain_pem != NULL); - - if (status->has_certificate) { - ts_cert_get_info(&status->cert_info); - } else { - memset(&status->cert_info, 0, sizeof(status->cert_info)); - } - return ESP_OK; } -esp_err_t ts_cert_get_info(ts_cert_info_t *info) +static esp_err_t ts_cert_get_info_locked(ts_cert_info_t *info) { - if (!s_initialized) return ESP_ERR_INVALID_STATE; if (!info) return ESP_ERR_INVALID_ARG; + memset(info, 0, sizeof(*info)); + if (!s_initialized) return ESP_ERR_INVALID_STATE; if (!s_certificate_pem) return ESP_ERR_NOT_FOUND; - - return ts_cert_parse_certificate(s_certificate_pem, strlen(s_certificate_pem) + 1, info); + refresh_metadata(); + *info = s_metadata; + evaluate_time(info, (int64_t)time(NULL)); + return info->validity == TS_CERT_VALIDITY_INVALID ? ESP_ERR_INVALID_ARG : ESP_OK; } -bool ts_cert_is_valid(void) +static bool ts_cert_is_valid_locked(void) { if (!s_certificate_pem) return false; ts_cert_info_t info; - if (ts_cert_get_info(&info) != ESP_OK) return false; + if (ts_cert_get_info_locked(&info) != ESP_OK) return false; return info.is_valid; } -int ts_cert_days_until_expiry(void) +static int ts_cert_days_until_expiry_locked(void) { if (!s_certificate_pem) return INT32_MAX; ts_cert_info_t info; - if (ts_cert_get_info(&info) != ESP_OK) return INT32_MAX; + if (ts_cert_get_info_locked(&info) != ESP_OK) return INT32_MAX; return info.days_until_expiry; } @@ -825,20 +865,35 @@ int ts_cert_days_until_expiry(void) /* Factory Reset */ /*===========================================================================*/ -esp_err_t ts_cert_factory_reset(void) +static esp_err_t ts_cert_factory_reset_locked(void) { if (!s_initialized) return ESP_ERR_INVALID_STATE; /* Erase all NVS keys */ - nvs_erase_key(s_nvs_handle, NVS_KEY_PRIVKEY); - nvs_erase_key(s_nvs_handle, NVS_KEY_CERT); - nvs_erase_key(s_nvs_handle, NVS_KEY_CA_CHAIN); - nvs_erase_key(s_nvs_handle, NVS_KEY_STATUS); - nvs_commit(s_nvs_handle); - + esp_err_t err = ESP_OK; + if (err == ESP_OK) { + err = nvs_erase_key(s_nvs_handle, NVS_KEY_PRIVKEY); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + } + if (err == ESP_OK) { + err = nvs_erase_key(s_nvs_handle, NVS_KEY_CERT); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + } + if (err == ESP_OK) { + err = nvs_erase_key(s_nvs_handle, NVS_KEY_CA_CHAIN); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + } + if (err == ESP_OK) { + err = nvs_erase_key(s_nvs_handle, NVS_KEY_STATUS); + if (err == ESP_ERR_NVS_NOT_FOUND) err = ESP_OK; + } + if (err == ESP_OK) err = nvs_commit(s_nvs_handle); + if (err != ESP_OK) { s_storage_error = true; return err; } + ++s_generation; + /* Securely clear memory */ if (s_private_key_pem) { - memset(s_private_key_pem, 0, strlen(s_private_key_pem)); + mbedtls_platform_zeroize(s_private_key_pem, strlen(s_private_key_pem)); free(s_private_key_pem); s_private_key_pem = NULL; } @@ -868,26 +923,18 @@ const char *ts_cert_status_to_str(ts_cert_status_t status) case TS_CERT_STATUS_ACTIVATED: return "activated"; case TS_CERT_STATUS_EXPIRED: return "expired"; case TS_CERT_STATUS_ERROR: return "error"; + case TS_CERT_STATUS_TIME_UNVERIFIED: return "time_unverified"; + case TS_CERT_STATUS_NOT_YET_VALID: return "not_yet_valid"; default: return "unknown"; } } -esp_err_t ts_cert_parse_certificate(const char *cert_pem, size_t cert_len, - ts_cert_info_t *info) +static esp_err_t info_from_crt(const mbedtls_x509_crt *crt, ts_cert_info_t *info) { - if (!cert_pem || !info) return ESP_ERR_INVALID_ARG; - - mbedtls_x509_crt crt; - mbedtls_x509_crt_init(&crt); - - int ret = mbedtls_x509_crt_parse(&crt, (const unsigned char *)cert_pem, cert_len); - if (ret != 0) { - mbedtls_x509_crt_free(&crt); - return ESP_ERR_INVALID_ARG; - } - + memset(info, 0, sizeof(*info)); + info->validity = TS_CERT_VALIDITY_INVALID; /* Extract subject CN */ - const mbedtls_x509_name *name = &crt.subject; + const mbedtls_x509_name *name = &crt->subject; info->subject_cn[0] = '\0'; info->subject_ou[0] = '\0'; while (name) { @@ -907,7 +954,7 @@ esp_err_t ts_cert_parse_certificate(const char *cert_pem, size_t cert_len, } /* Extract issuer CN */ - name = &crt.issuer; + name = &crt->issuer; info->issuer_cn[0] = '\0'; while (name) { if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0) { @@ -920,36 +967,332 @@ esp_err_t ts_cert_parse_certificate(const char *cert_pem, size_t cert_len, name = name->next; } - /* Convert validity times */ - struct tm tm_from, tm_to; - tm_from.tm_year = crt.valid_from.year - 1900; - tm_from.tm_mon = crt.valid_from.mon - 1; - tm_from.tm_mday = crt.valid_from.day; - tm_from.tm_hour = crt.valid_from.hour; - tm_from.tm_min = crt.valid_from.min; - tm_from.tm_sec = crt.valid_from.sec; - info->not_before = mktime(&tm_from); - - tm_to.tm_year = crt.valid_to.year - 1900; - tm_to.tm_mon = crt.valid_to.mon - 1; - tm_to.tm_mday = crt.valid_to.day; - tm_to.tm_hour = crt.valid_to.hour; - tm_to.tm_min = crt.valid_to.min; - tm_to.tm_sec = crt.valid_to.sec; - info->not_after = mktime(&tm_to); - - /* Serial number (hex) */ - for (size_t i = 0; i < crt.serial.len && i < 32; i++) { - sprintf(info->serial + i * 2, "%02X", crt.serial.p[i]); + if (!ts_cert_time_utc(crt->valid_from.year, crt->valid_from.mon, crt->valid_from.day, + crt->valid_from.hour, crt->valid_from.min, crt->valid_from.sec, &info->not_before) || + !ts_cert_time_utc(crt->valid_to.year, crt->valid_to.mon, crt->valid_to.day, + crt->valid_to.hour, crt->valid_to.min, crt->valid_to.sec, &info->not_after) || + info->not_after < info->not_before) { + return ESP_ERR_INVALID_ARG; } + info->serial_truncated = ts_cert_hex(crt->serial.p, crt->serial.len, info->serial, sizeof(info->serial)); + info->validity = TS_CERT_VALIDITY_VALID; + return ESP_OK; +} + +esp_err_t ts_cert_parse_certificate(const char *cert_pem, size_t cert_len, + ts_cert_info_t *info) +{ + if (!info) return ESP_ERR_INVALID_ARG; + memset(info, 0, sizeof(*info)); + info->validity = TS_CERT_VALIDITY_INVALID; + if (!cert_pem || cert_len <= 1 || cert_pem[cert_len-1] != 0 || memchr(cert_pem, 0, cert_len-1)) + return ESP_ERR_INVALID_ARG; - /* Calculate validity */ - time_t now; - time(&now); + mbedtls_x509_crt crt; + mbedtls_x509_crt_init(&crt); - info->is_valid = (now >= info->not_before && now <= info->not_after); - info->days_until_expiry = (int)((info->not_after - now) / 86400); + int ret = mbedtls_x509_crt_parse(&crt, (const unsigned char *)cert_pem, cert_len); + if (ret != 0) { + mbedtls_x509_crt_free(&crt); + return ESP_ERR_INVALID_ARG; + } + ret = info_from_crt(&crt, info); + if (ret == ESP_OK) evaluate_time(info, (int64_t)time(NULL)); mbedtls_x509_crt_free(&crt); + return ret; +} + +static void evaluate_time(ts_cert_info_t *info, int64_t now) +{ + info->is_valid = false; + info->seconds_until_expiry = 0; + info->days_until_expiry = 0; + info->time_ready = ts_cert_time_ready(now, TS_TIME_MIN_VALID_YEAR); + if (info->validity == TS_CERT_VALIDITY_NONE || info->validity == TS_CERT_VALIDITY_INVALID) return; + if (!info->time_ready) { info->validity = TS_CERT_VALIDITY_TIME_UNVERIFIED; return; } + info->seconds_until_expiry = info->not_after - now; + info->days_until_expiry = ts_cert_time_days(info->seconds_until_expiry); + info->validity = now < info->not_before ? TS_CERT_VALIDITY_NOT_YET_VALID : + now > info->not_after ? TS_CERT_VALIDITY_EXPIRED : TS_CERT_VALIDITY_VALID; + info->is_valid = info->validity == TS_CERT_VALIDITY_VALID; +} + +static void refresh_metadata(void) +{ + if (s_metadata_generation == s_generation) return; + memset(&s_metadata, 0, sizeof(s_metadata)); + s_key_valid = s_key_matches = s_ca_valid = false; + s_fingerprint[0] = 0; + mbedtls_pk_context key; + mbedtls_x509_crt crt, ca; + mbedtls_pk_init(&key); mbedtls_x509_crt_init(&crt); mbedtls_x509_crt_init(&ca); + if (s_private_key_pem && init_rng() == ESP_OK) + s_key_valid = mbedtls_pk_parse_key(&key, (const unsigned char *)s_private_key_pem, + strlen(s_private_key_pem)+1, NULL, 0, mbedtls_ctr_drbg_random, &s_ctr_drbg) == 0; + if (s_certificate_pem) { + s_metadata.validity = TS_CERT_VALIDITY_INVALID; + if (mbedtls_x509_crt_parse(&crt, (const unsigned char *)s_certificate_pem, strlen(s_certificate_pem)+1) == 0) { + info_from_crt(&crt, &s_metadata); + s_key_matches = s_key_valid && mbedtls_pk_check_pair(&crt.pk, &key, mbedtls_ctr_drbg_random, &s_ctr_drbg) == 0; + unsigned char hash[32]; + if (mbedtls_sha256(crt.raw.p, crt.raw.len, hash, 0) == 0) + ts_cert_hex(hash, sizeof(hash), s_fingerprint, sizeof(s_fingerprint)); + } + } + if (s_ca_chain_pem) + s_ca_valid = mbedtls_x509_crt_parse(&ca, (const unsigned char *)s_ca_chain_pem, strlen(s_ca_chain_pem)+1) == 0; + mbedtls_pk_free(&key); mbedtls_x509_crt_free(&crt); mbedtls_x509_crt_free(&ca); + s_metadata_generation = s_generation; +} + +bool ts_cert_prerequisites(const ts_cert_pki_status_t *s, bool require_ca) +{ + return s && !s->storage_error && s->time_ready && s->has_private_key && s->key_valid && + s->has_certificate && s->key_matches && s->cert_info.is_valid && + (!require_ca || (s->has_ca_chain && s->ca_valid)); +} + +const char *ts_cert_validity_to_str(ts_cert_validity_t v) +{ + static const char *names[] = {"none", "invalid", "time_unverified", "not_yet_valid", "valid", "expired"}; + return (unsigned)v < sizeof(names)/sizeof(names[0]) ? names[v] : "invalid"; +} +const char *ts_cert_op_error_to_str(ts_cert_op_error_t e) +{ + static const char *names[] = {"Saved", "Certificate module not ready", "Provide non-empty PEM text", + "PEM exceeds 3999 content bytes (4000 including NUL)", "Cannot parse certificate PEM", + "Generate the device key first", "Stored private key is invalid", "Certificate does not match device key; use its CSR", + "Insufficient device memory", "Credential storage failed; restart and check stored materials", "Device cryptographic operation failed"}; + return (unsigned)e < sizeof(names)/sizeof(names[0]) ? names[e] : "Certificate operation failed"; +} + +void ts_cert_free_snapshot(ts_cert_snapshot_t *s) +{ + if (!s) return; + if (s->key) mbedtls_platform_zeroize(s->key, strlen(s->key)); + free(s->key); free(s->certificate); free(s->ca); + memset(s, 0, sizeof(*s)); +} + +static esp_err_t ts_cert_get_snapshot_locked(bool require_ca, ts_cert_snapshot_t *snapshot) +{ + if (!snapshot) return ESP_ERR_INVALID_ARG; + memset(snapshot, 0, sizeof(*snapshot)); + ts_cert_pki_status_t status; + esp_err_t err = ts_cert_get_status_locked(&status); + if (err != ESP_OK) return err; + if (!ts_cert_prerequisites(&status, require_ca)) return ESP_ERR_INVALID_STATE; + snapshot->key = copy_pem(s_private_key_pem, strlen(s_private_key_pem)+1); + snapshot->certificate = copy_pem(s_certificate_pem, strlen(s_certificate_pem)+1); + if (s_ca_chain_pem && s_ca_valid) snapshot->ca = copy_pem(s_ca_chain_pem, strlen(s_ca_chain_pem)+1); + if (!snapshot->key || !snapshot->certificate || (require_ca && !snapshot->ca)) { + ts_cert_free_snapshot(snapshot); return ESP_ERR_NO_MEM; + } + snapshot->generation = s_generation; + memcpy(snapshot->certificate_sha256, s_fingerprint, sizeof(s_fingerprint)); return ESP_OK; } + +/* All public cache/RNG operations take the same lock; events are posted after release. + * Lock order: material only -> unlock -> event; never material -> TLS/service manager. + */ +static void material_unlock(uint32_t previous, uint32_t kind) +{ + uint32_t generation = s_generation; + xSemaphoreGive(s_mutex); + if (generation != previous) { + struct { uint32_t generation; uint32_t kind; } event = {generation, kind}; + esp_err_t err = ts_event_post(TS_EVENT_BASE_PKI, TS_EVENT_PKI_MATERIAL_CHANGED, &event, sizeof(event), 0); + if (err != ESP_OK) ESP_LOGW(TAG, "Material notification lost: %s", esp_err_to_name(err)); + } +} + +esp_err_t ts_cert_init(void) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_init_locked(); + material_unlock(previous, 0); + return result; +} + +void ts_cert_deinit(void) +{ + material_lock(); + uint32_t previous = s_generation; + ts_cert_deinit_locked(); + material_unlock(previous, 0); +} + +esp_err_t ts_cert_generate_keypair(void) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_generate_keypair_locked(); + material_unlock(previous, 3); + return result; +} + +bool ts_cert_has_keypair(void) +{ + material_lock(); + uint32_t previous = s_generation; + bool result = ts_cert_has_keypair_locked(); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_delete_keypair(void) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_delete_keypair_locked(); + material_unlock(previous, 4); + return result; +} + +esp_err_t ts_cert_generate_csr(const ts_cert_csr_opts_t *opts, + char *csr_pem, size_t *csr_len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_generate_csr_locked(opts, csr_pem, csr_len); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_generate_csr_default(char *csr_pem, size_t *csr_len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_generate_csr_default_locked(csr_pem, csr_len); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_install_certificate_ex(const char *pem, size_t len, ts_cert_op_error_t *detail) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_install_certificate_ex_locked(pem, len, detail); + material_unlock(previous, 1); + return result; +} + +esp_err_t ts_cert_install_ca_chain_ex(const char *pem, size_t len, ts_cert_op_error_t *detail) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_install_ca_chain_ex_locked(pem, len, detail); + material_unlock(previous, 2); + return result; +} + +esp_err_t ts_cert_install_certificate(const char *pem, size_t len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_install_certificate_locked(pem, len); + material_unlock(previous, 1); + return result; +} + +esp_err_t ts_cert_install_ca_chain(const char *pem, size_t len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_install_ca_chain_locked(pem, len); + material_unlock(previous, 2); + return result; +} + +esp_err_t ts_cert_get_certificate(char *cert_pem, size_t *cert_len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_get_certificate_locked(cert_pem, cert_len); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_get_private_key(char *key_pem, size_t *key_len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_get_private_key_locked(key_pem, key_len); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_get_ca_chain(char *ca_chain_pem, size_t *ca_chain_len) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_get_ca_chain_locked(ca_chain_pem, ca_chain_len); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_refresh_status(void) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_refresh_status_locked(); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_get_status(ts_cert_pki_status_t *status) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_get_status_locked(status); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_get_info(ts_cert_info_t *info) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_get_info_locked(info); + material_unlock(previous, 0); + return result; +} + +bool ts_cert_is_valid(void) +{ + material_lock(); + uint32_t previous = s_generation; + bool result = ts_cert_is_valid_locked(); + material_unlock(previous, 0); + return result; +} + +int ts_cert_days_until_expiry(void) +{ + material_lock(); + uint32_t previous = s_generation; + int result = ts_cert_days_until_expiry_locked(); + material_unlock(previous, 0); + return result; +} + +esp_err_t ts_cert_factory_reset(void) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_factory_reset_locked(); + material_unlock(previous, 4); + return result; +} + +esp_err_t ts_cert_get_snapshot(bool require_ca, ts_cert_snapshot_t *snapshot) +{ + material_lock(); + uint32_t previous = s_generation; + esp_err_t result = ts_cert_get_snapshot_locked(require_ca, snapshot); + material_unlock(previous, 0); + return result; +} diff --git a/components/ts_cert/src/ts_cert_time.c b/components/ts_cert/src/ts_cert_time.c new file mode 100644 index 0000000..9cf8077 --- /dev/null +++ b/components/ts_cert/src/ts_cert_time.c @@ -0,0 +1,42 @@ +#include "ts_cert_time.h" +#include + +bool ts_cert_time_utc(int y, int m, int d, int h, int min, int s, int64_t *out) +{ + static const int before[] = {0,31,59,90,120,151,181,212,243,273,304,334}; + static const int days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; + if (!out || y < 1 || y > 9999 || m < 1 || m > 12 || h < 0 || h > 23 || + min < 0 || min > 59 || s < 0 || s > 59) return false; + bool leap = y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); + if (d < 1 || d > days[m-1] + (m == 2 && leap)) return false; + int64_t prev = y - 1; + int64_t n = 365 * (int64_t)(y - 1970) + prev/4 - prev/100 + prev/400 - 477; + n += before[m-1] + (leap && m > 2) + d - 1; + *out = n * 86400 + h * 3600 + min * 60 + s; + return true; +} + +int ts_cert_time_days(int64_t seconds) +{ + int64_t days = seconds / 86400 - (seconds < 0 && seconds % 86400 != 0); + return days > INT_MAX ? INT_MAX : days < INT_MIN ? INT_MIN : (int)days; +} + +bool ts_cert_time_ready(int64_t now, int minimum_year) +{ + int64_t threshold; + return now != -1 && ts_cert_time_utc(minimum_year, 1, 1, 0, 0, 0, &threshold) && now >= threshold; +} + +bool ts_cert_hex(const unsigned char *bytes, size_t length, char *out, size_t capacity) +{ + static const char hex[] = "0123456789ABCDEF"; + if (!capacity) return length != 0; + size_t n = length < (capacity-1)/2 ? length : (capacity-1)/2; + for (size_t i = 0; i < n; ++i) { + out[2*i] = hex[bytes[i] >> 4]; + out[2*i+1] = hex[bytes[i] & 15]; + } + out[2*n] = 0; + return n < length; +} diff --git a/components/ts_console/commands/ts_cmd_auto.c b/components/ts_console/commands/ts_cmd_auto.c index d07eb7e..864b589 100644 --- a/components/ts_console/commands/ts_cmd_auto.c +++ b/components/ts_console/commands/ts_cmd_auto.c @@ -246,6 +246,7 @@ static int cmd_auto_list(bool json_output) rule.conditions.count, rule.action_count); } + ts_rule_release(&rule); } } diff --git a/components/ts_console/commands/ts_cmd_pki.c b/components/ts_console/commands/ts_cmd_pki.c index 24200e0..82945b8 100644 --- a/components/ts_console/commands/ts_cmd_pki.c +++ b/components/ts_console/commands/ts_cmd_pki.c @@ -78,6 +78,7 @@ static void print_status_json(const ts_cert_pki_status_t *status) ts_console_printf(" \"issuer\": \"%s\",\n", status->cert_info.issuer_cn); ts_console_printf(" \"serial\": \"%s\",\n", status->cert_info.serial); ts_console_printf(" \"valid\": %s,\n", status->cert_info.is_valid ? "true" : "false"); + ts_console_printf(" \"validity\": \"%s\",\n", ts_cert_validity_to_str(status->cert_info.validity)); ts_console_printf(" \"days_until_expiry\": %d\n", status->cert_info.days_until_expiry); ts_console_printf(" }\n"); } else { @@ -99,7 +100,7 @@ static void print_status_text(const ts_cert_pki_status_t *status) switch (status->status) { case TS_CERT_STATUS_ACTIVATED: - status_str = "ACTIVATED"; + status_str = "TIME VALID"; status_color = "\033[32m"; /* Green */ break; case TS_CERT_STATUS_KEY_GENERATED: @@ -110,6 +111,12 @@ static void print_status_text(const ts_cert_pki_status_t *status) status_str = "CSR PENDING"; status_color = "\033[33m"; /* Yellow */ break; + case TS_CERT_STATUS_TIME_UNVERIFIED: + status_str = "TIME UNVERIFIED"; status_color = "\033[33m"; break; + case TS_CERT_STATUS_NOT_YET_VALID: + status_str = "NOT YET VALID"; status_color = "\033[33m"; break; + case TS_CERT_STATUS_ERROR: + status_str = "MATERIAL ERROR"; status_color = "\033[31m"; break; case TS_CERT_STATUS_EXPIRED: status_str = "EXPIRED"; status_color = "\033[31m"; /* Red */ @@ -142,7 +149,7 @@ static void print_status_text(const ts_cert_pki_status_t *status) status->cert_info.days_until_expiry); } } else { - ts_console_printf("║ Validity: \033[31mExpired\033[0m ║\n"); + ts_console_printf("║ Validity: %-30s ║\n", ts_cert_validity_to_str(status->cert_info.validity)); } } @@ -352,7 +359,7 @@ static int cmd_pki_install(const char *filepath, bool is_ca) long file_size = ftell(f); fseek(f, 0, SEEK_SET); - if (file_size <= 0 || file_size > TS_CERT_PEM_MAX_LEN) { + if (file_size <= 0 || file_size >= TS_CERT_INSTALL_MAX_LEN) { fclose(f); ts_console_printf("Error: Invalid file size\n"); return 1; @@ -488,7 +495,9 @@ static int cmd_pki_handler(int argc, char **argv) ts_console_printf(" Issuer: %s\n", info.issuer_cn); ts_console_printf(" Serial: %s\n", info.serial); ts_console_printf(" Valid: %s\n", info.is_valid ? "Yes" : "No"); - ts_console_printf(" Expires: %d days\n", info.days_until_expiry); + ts_console_printf(" Time validity: %s\n", ts_cert_validity_to_str(info.validity)); + if (info.time_ready && info.validity != TS_CERT_VALIDITY_INVALID) + ts_console_printf(" Expires: %d days\n", info.days_until_expiry); return 0; } diff --git a/components/ts_console/commands/ts_cmd_ssh.c b/components/ts_console/commands/ts_cmd_ssh.c index db7d598..0a0b5a1 100644 --- a/components/ts_console/commands/ts_cmd_ssh.c +++ b/components/ts_console/commands/ts_cmd_ssh.c @@ -253,6 +253,11 @@ static esp_err_t verify_host_key(ts_ssh_session_t session, bool verbose) return ret; } +static esp_err_t cli_verify_before_auth(ts_ssh_session_t session, void *unused) +{ + return verify_host_key(session, false); +} + /*===========================================================================*/ /* Ctrl+C 检测任务 */ @@ -407,6 +412,7 @@ static const char *shell_input_callback(size_t *out_len, void *user_data) } else if (ch == 0x1C) { /* Ctrl+\ - 退出 Shell */ ts_console_printf("\n^\\ (Exit shell)\n"); ts_console_request_interrupt(); + ts_ssh_shell_request_close(shell); return NULL; } @@ -454,7 +460,7 @@ static int do_ssh_shell(const char *host, int port, const char *user, } /* 连接 */ - ret = ts_ssh_connect(session); + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); if (ret != ESP_OK) { ts_console_printf("Error: %s\n", ts_ssh_get_error(session)); ts_ssh_session_destroy(session); @@ -563,7 +569,7 @@ static int do_ssh_forward(const char *host, int port, const char *user, } /* 连接 */ - ret = ts_ssh_connect(session); + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); if (ret != ESP_OK) { ts_console_printf("Error: %s\n", ts_ssh_get_error(session)); ts_ssh_session_destroy(session); @@ -864,7 +870,7 @@ static int do_ssh_copy_id(const char *host, int port, const char *user, return 1; } - ret = ts_ssh_connect(session); + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); if (ret != ESP_OK) { ts_console_printf("FAILED\n"); ts_console_printf(" Error: %s\n", ts_ssh_get_error(session)); @@ -988,7 +994,7 @@ static int do_ssh_copy_id(const char *host, int port, const char *user, return 1; } - ret = ts_ssh_connect(session); + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); if (ret != ESP_OK) { const char *error_msg = ts_ssh_get_error(session); @@ -1196,7 +1202,7 @@ static int do_ssh_revoke(const char *host, int port, const char *user, } /* 连接 */ - ret = ts_ssh_connect(session); + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); if (ret != ESP_OK) { ts_console_printf("FAILED\n"); ts_console_printf("Error: %s\n", ts_ssh_get_error(session)); diff --git a/components/ts_core/ts_event/include/ts_event.h b/components/ts_core/ts_event/include/ts_event.h index 25d5eb9..10f1505 100644 --- a/components/ts_core/ts_event/include/ts_event.h +++ b/components/ts_core/ts_event/include/ts_event.h @@ -166,6 +166,9 @@ typedef struct { #define TS_EVENT_BASE_OTA "ts_ota" /** 时间事件 */ +#define TS_EVENT_BASE_PKI "ts_pki" +#define TS_EVENT_PKI_MATERIAL_CHANGED 0x0001 + #define TS_EVENT_BASE_TIME "ts_time" /* ============================================================================ @@ -369,6 +372,12 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, */ esp_err_t ts_event_unregister(ts_event_handler_handle_t handle); +/** Stop new invocations and drain existing callbacks. Timeout retains the handle + * for retry; only ESP_OK / NOT_FOUND permits freeing user_data. Never call from + * an event callback (including post_sync); use nonblocking unregister there. */ +esp_err_t ts_event_unregister_sync(ts_event_handler_handle_t handle, uint32_t timeout_ms); +bool ts_event_in_callback(void); + /** * @brief 取消注册指定事件的所有处理器 * diff --git a/components/ts_core/ts_event/src/ts_event.c b/components/ts_core/ts_event/src/ts_event.c index e80dee2..4dc94cf 100644 --- a/components/ts_core/ts_event/src/ts_event.c +++ b/components/ts_core/ts_event/src/ts_event.c @@ -10,6 +10,7 @@ #include #include +#include #include "ts_event.h" #include "esp_log.h" #include "esp_timer.h" @@ -50,6 +51,10 @@ typedef struct ts_event_handler_instance { ts_event_priority_t min_priority; ts_event_handler_t handler; void *user_data; + bool retired; + bool drain_pending; + unsigned refs; /* snapshots + synchronous unregister waiters */ + unsigned in_flight; struct ts_event_handler_instance *next; } ts_event_handler_instance_t; @@ -80,7 +85,7 @@ typedef struct { ts_event_handler_instance_t *handlers; size_t handler_count; ts_event_stats_t stats; - bool running; + atomic_bool running; } ts_event_context_t; /* ============================================================================ @@ -89,6 +94,14 @@ typedef struct { static ts_event_context_t s_event_ctx = {0}; +/* Includes synchronous posts from arbitrary tasks and nested dispatch. */ +typedef struct dispatch_scope { + TaskHandle_t task; + struct dispatch_scope *next; +} dispatch_scope_t; +static dispatch_scope_t *s_dispatch_scopes; + + /* ============================================================================ * 私有函数声明 * ========================================================================== */ @@ -169,6 +182,7 @@ esp_err_t ts_event_deinit(void) return ESP_ERR_INVALID_STATE; } + if (ts_event_in_callback()) return ESP_ERR_INVALID_STATE; ESP_LOGI(TAG, "Deinitializing event system..."); // 停止事件循环 @@ -178,17 +192,18 @@ esp_err_t ts_event_deinit(void) ts_event_internal_t dummy = {0}; xQueueSend(s_event_ctx.event_queue, &dummy, 0); - // 等待任务结束 - vTaskDelay(pdMS_TO_TICKS(100)); - - // 删除任务 - if (s_event_ctx.event_task != NULL) { - vTaskDelete(s_event_ctx.event_task); - s_event_ctx.event_task = NULL; + int64_t deadline = esp_timer_get_time() + 6000000; + for (;;) { + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + bool draining = s_event_ctx.event_task || s_dispatch_scopes; + for (ts_event_handler_instance_t *p = s_event_ctx.handlers; p; p=p->next) + if (p->refs || p->drain_pending) draining = true; + if (!draining) break; /* retain lock for final free */ + xSemaphoreGive(s_event_ctx.mutex); + if (esp_timer_get_time() >= deadline) return ESP_ERR_TIMEOUT; + vTaskDelay(1); } - xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); - // 释放所有处理器 ts_event_handler_instance_t *handler = s_event_ctx.handlers; while (handler != NULL) { @@ -250,11 +265,6 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, return ESP_ERR_INVALID_STATE; } - if (s_event_ctx.handler_count >= TS_EVENT_HANDLERS_MAX) { - ESP_LOGE(TAG, "Maximum handlers reached"); - return ESP_ERR_NO_MEM; - } - ts_event_handler_instance_t *node = TS_EVT_CALLOC(1, sizeof(ts_event_handler_instance_t)); if (node == NULL) { return ESP_ERR_NO_MEM; @@ -268,6 +278,11 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + if (!s_event_ctx.running || s_event_ctx.handler_count >= TS_EVENT_HANDLERS_MAX) { + xSemaphoreGive(s_event_ctx.mutex); + free(node); + return ESP_ERR_NO_MEM; + } node->next = s_event_ctx.handlers; s_event_ctx.handlers = node; s_event_ctx.handler_count++; @@ -285,78 +300,95 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, return ESP_OK; } -esp_err_t ts_event_unregister(ts_event_handler_handle_t handle) +/* Retired nodes remain discoverable while a drain waiter owns them. */ +static void reclaim_handler(ts_event_handler_instance_t *node) { - if (handle == NULL) { - return ESP_ERR_INVALID_ARG; - } - - if (!s_event_ctx.initialized) { - return ESP_ERR_INVALID_STATE; - } + if (!node->retired || node->refs || node->drain_pending) return; + ts_event_handler_instance_t **link = &s_event_ctx.handlers; + while (*link && *link != node) link = &(*link)->next; + if (*link) { *link = node->next; free(node); } +} +bool ts_event_in_callback(void) +{ + if (!s_event_ctx.initialized) return false; + TaskHandle_t self = xTaskGetCurrentTaskHandle(); + bool found = false; xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + for (dispatch_scope_t *p = s_dispatch_scopes; p; p = p->next) + if (p->task == self) { found = true; break; } + xSemaphoreGive(s_event_ctx.mutex); + return found; +} - ts_event_handler_instance_t *prev = NULL; +static esp_err_t unregister_handler(ts_event_handler_handle_t handle, bool wait, + uint32_t timeout_ms) +{ + if (!handle) return ESP_ERR_INVALID_ARG; + if (!s_event_ctx.initialized) return ESP_ERR_INVALID_STATE; + if (wait && ts_event_in_callback()) return ESP_ERR_INVALID_STATE; + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ts_event_handler_instance_t *node = s_event_ctx.handlers; - ts_event_handler_instance_t *target = (ts_event_handler_instance_t *)handle; - - while (node != NULL) { - if (node == target) { - if (prev == NULL) { - s_event_ctx.handlers = node->next; - } else { - prev->next = node->next; - } - s_event_ctx.handler_count--; - s_event_ctx.stats.handlers_registered = s_event_ctx.handler_count; - + while (node && node != handle) node = node->next; + if (!node) { xSemaphoreGive(s_event_ctx.mutex); return ESP_ERR_NOT_FOUND; } + if (!node->retired) { + node->retired = true; + s_event_ctx.handler_count--; + s_event_ctx.stats.handlers_registered = s_event_ctx.handler_count; + } + if (!wait) { + reclaim_handler(node); + xSemaphoreGive(s_event_ctx.mutex); + return ESP_OK; + } + node->drain_pending = true; + node->refs++; /* pins both node and its position while the lock is dropped */ + int64_t deadline = esp_timer_get_time() + (int64_t)timeout_ms * 1000; + while (node->in_flight) { + xSemaphoreGive(s_event_ctx.mutex); + vTaskDelay(1); + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + if (node->in_flight && esp_timer_get_time() >= deadline) { + /* Keep a retired registry reference for retry, even after callbacks end. */ + node->refs--; xSemaphoreGive(s_event_ctx.mutex); - free(node); - return ESP_OK; + return ESP_ERR_TIMEOUT; } - prev = node; - node = node->next; } - + node->refs--; + node->drain_pending = false; + reclaim_handler(node); xSemaphoreGive(s_event_ctx.mutex); - return ESP_ERR_NOT_FOUND; + return ESP_OK; } -esp_err_t ts_event_unregister_all(ts_event_base_t event_base, ts_event_id_t event_id) +esp_err_t ts_event_unregister(ts_event_handler_handle_t handle) { - if (!s_event_ctx.initialized) { - return ESP_ERR_INVALID_STATE; - } + return unregister_handler(handle, false, 0); +} - xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); +esp_err_t ts_event_unregister_sync(ts_event_handler_handle_t handle, uint32_t timeout_ms) +{ + return unregister_handler(handle, true, timeout_ms); +} - ts_event_handler_instance_t *prev = NULL; +esp_err_t ts_event_unregister_all(ts_event_base_t base, ts_event_id_t id) +{ + if (!s_event_ctx.initialized) return ESP_ERR_INVALID_STATE; + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ts_event_handler_instance_t *node = s_event_ctx.handlers; - - while (node != NULL) { - bool match = (event_base == NULL || - (node->base != NULL && strcmp(node->base, event_base) == 0)); - if (match && (event_id == TS_EVENT_ANY_ID || node->id == event_id)) { - ts_event_handler_instance_t *to_delete = node; - if (prev == NULL) { - s_event_ctx.handlers = node->next; - node = s_event_ctx.handlers; - } else { - prev->next = node->next; - node = node->next; - } + while (node) { + ts_event_handler_instance_t *next = node->next; + if (!node->retired && (!base || (node->base && !strcmp(base, node->base))) && + (id == TS_EVENT_ANY_ID || id == node->id)) { + node->retired = true; s_event_ctx.handler_count--; - free(to_delete); - } else { - prev = node; - node = node->next; + reclaim_handler(node); } + node = next; } - s_event_ctx.stats.handlers_registered = s_event_ctx.handler_count; xSemaphoreGive(s_event_ctx.mutex); - return ESP_OK; } @@ -659,6 +691,9 @@ static void event_loop_task(void *arg) } ESP_LOGI(TAG, "Event loop task ended"); + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + s_event_ctx.event_task = NULL; + xSemaphoreGive(s_event_ctx.mutex); vTaskDelete(NULL); } @@ -683,30 +718,41 @@ static void dispatch_event(const ts_event_internal_t *internal_event) xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); - ts_event_handler_instance_t *handler = s_event_ctx.handlers; - while (handler != NULL) { - if (handler_matches(handler, internal_event)) { - // 释放锁来调用处理器(避免死锁) + ts_event_handler_instance_t *snapshot[TS_EVENT_HANDLERS_MAX]; + size_t count = 0; + dispatch_scope_t scope = {.task = xTaskGetCurrentTaskHandle(), .next = s_dispatch_scopes}; + s_dispatch_scopes = &scope; + for (ts_event_handler_instance_t *p = s_event_ctx.handlers; p; p = p->next) { + if (!p->retired && handler_matches(p, internal_event)) { + p->refs++; + snapshot[count++] = p; + } + } + for (size_t i = 0; i < count; ++i) { + ts_event_handler_instance_t *p = snapshot[i]; + if (!p->retired) { + p->in_flight++; + ts_event_handler_t fn = p->handler; + void *data = p->user_data; xSemaphoreGive(s_event_ctx.mutex); - - if (handler->handler != NULL) { - handler->handler(&event, handler->user_data); - } - - s_event_ctx.stats.events_delivered++; - + fn(&event, data); xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + p->in_flight--; + s_event_ctx.stats.events_delivered++; } - handler = handler->next; + p->refs--; + reclaim_handler(p); } - - xSemaphoreGive(s_event_ctx.mutex); + dispatch_scope_t **link = &s_dispatch_scopes; + while (*link != &scope) link = &(*link)->next; + *link = scope.next; // 更新统计 int64_t elapsed = esp_timer_get_time() - start_time; if (elapsed > s_event_ctx.stats.max_delivery_time_us) { s_event_ctx.stats.max_delivery_time_us = (uint32_t)elapsed; } + xSemaphoreGive(s_event_ctx.mutex); } static bool handler_matches(const ts_event_handler_instance_t *handler, @@ -718,7 +764,7 @@ static bool handler_matches(const ts_event_handler_instance_t *handler, } // 检查事件基础 - if (handler->base != TS_EVENT_ANY_BASE && handler->base != NULL) { + if (handler->base != NULL && strcmp(handler->base, TS_EVENT_ANY_BASE) != 0) { if (event->base == NULL || strcmp(handler->base, event->base) != 0) { return false; } diff --git a/components/ts_core/ts_log/include/ts_log.h b/components/ts_core/ts_log/include/ts_log.h index cd0ca12..3779244 100644 --- a/components/ts_core/ts_log/include/ts_log.h +++ b/components/ts_core/ts_log/include/ts_log.h @@ -115,6 +115,8 @@ typedef struct { size_t buffer_capacity; /**< 缓冲区容量 */ size_t buffer_count; /**< 当前缓冲区中的日志数 */ uint32_t total_captured; /**< 总捕获日志数(含溢出覆盖的)*/ + uint32_t capture_dropped; + uint32_t capture_truncated; uint32_t dropped; /**< 丢弃的日志数 */ bool esp_log_capture_enabled; /**< ESP_LOG 捕获是否启用 */ } ts_log_stats_t; diff --git a/components/ts_core/ts_log/src/ts_log.c b/components/ts_core/ts_log/src/ts_log.c index 327aeb9..441199f 100644 --- a/components/ts_core/ts_log/src/ts_log.c +++ b/components/ts_core/ts_log/src/ts_log.c @@ -1,3 +1,5 @@ +#include "ts_log_preview.h" +#include /** * @file ts_log.c * @brief TianShanOS Logging System Implementation @@ -72,6 +74,7 @@ typedef struct ts_log_tag_level { * @brief 回调节点 */ typedef struct ts_log_callback_node { + unsigned readers; ts_log_callback_t callback; ts_log_level_t min_level; void *user_data; @@ -92,7 +95,7 @@ typedef struct { * @brief 日志上下文 */ typedef struct { - bool initialized; + _Atomic bool initialized; SemaphoreHandle_t mutex; ts_log_level_t global_level; uint32_t output_mask; @@ -106,9 +109,12 @@ typedef struct { FILE *log_file; size_t file_size; int file_index; - vprintf_like_t original_vprintf; /**< 原始 vprintf 函数指针 */ - bool esp_log_capture_enabled; /**< 是否启用 ESP_LOG 捕获 */ + _Atomic(vprintf_like_t) original_vprintf; /**< 原始 vprintf 函数指针 */ + _Atomic bool esp_log_capture_enabled; /**< 是否启用 ESP_LOG 捕获 */ uint32_t total_logs_captured; /**< 总捕获日志数(含溢出) */ + _Atomic uint32_t capture_dropped; + _Atomic uint32_t capture_truncated; + unsigned active_writers; uint32_t logs_dropped; /**< 因缓冲区满丢弃的日志数 */ } ts_log_context_t; @@ -117,36 +123,53 @@ typedef struct { * ========================================================================== */ static ts_log_context_t s_log_ctx = {0}; +static SemaphoreHandle_t s_log_io_mutex; +static portMUX_TYPE s_capture_lock = portMUX_INITIALIZER_UNLOCKED; +static struct { + bool busy; + char text[512]; + ts_log_entry_t entry; +} s_capture[2]; +_Static_assert(sizeof(s_capture) <= 2048, "log capture RAM budget"); /* ============================================================================ * 私有函数声明 * ========================================================================== */ -static void log_output_console(const ts_log_entry_t *entry); +static void log_output_console(const ts_log_entry_t *entry, const char *format, va_list args); static void log_output_file(const ts_log_entry_t *entry); static void log_output_buffer(const ts_log_entry_t *entry); static void notify_callbacks(const ts_log_entry_t *entry); static ts_log_level_t get_effective_level(const char *tag); static void rotate_log_file(void); static int ts_log_vprintf_hook(const char *fmt, va_list args); -static void parse_esp_log_and_store(const char *log_line); +static void parse_esp_log(const char *log_line, ts_log_entry_t *out, bool clipped); /* ============================================================================ * 初始化和反初始化 * ========================================================================== */ +static atomic_bool s_log_lifecycle_busy; + esp_err_t ts_log_init(void) { + if (atomic_exchange(&s_log_lifecycle_busy, true)) + return ESP_ERR_INVALID_STATE; if (s_log_ctx.initialized) { + atomic_store(&s_log_lifecycle_busy, false); return ESP_ERR_INVALID_STATE; } ESP_LOGI(TAG, "Initializing TianShanOS Logging System..."); // 创建互斥锁 - s_log_ctx.mutex = xSemaphoreCreateMutex(); - if (s_log_ctx.mutex == NULL) { + if (!s_log_ctx.mutex) + s_log_ctx.mutex = xSemaphoreCreateMutex(); + if (!s_log_io_mutex) + s_log_io_mutex = xSemaphoreCreateMutex(); + if (s_log_ctx.mutex == NULL || !s_log_io_mutex) { ESP_LOGE(TAG, "Failed to create mutex"); + atomic_store(&s_log_lifecycle_busy, false); return ESP_ERR_NO_MEM; } @@ -220,12 +243,13 @@ esp_err_t ts_log_init(void) s_log_ctx.total_logs_captured = 0; s_log_ctx.logs_dropped = 0; + portENTER_CRITICAL(&s_capture_lock); s_log_ctx.initialized = true; + portEXIT_CRITICAL(&s_capture_lock); // 安装 ESP_LOG vprintf 钩子(捕获所有 ESP-IDF 日志) #ifdef CONFIG_TS_LOG_CAPTURE_ESP_LOG - s_log_ctx.esp_log_capture_enabled = true; - s_log_ctx.original_vprintf = esp_log_set_vprintf(ts_log_vprintf_hook); + ts_log_enable_esp_capture(true); ESP_LOGI(TAG, "ESP_LOG capture hook installed"); #else s_log_ctx.esp_log_capture_enabled = false; @@ -236,52 +260,59 @@ esp_err_t ts_log_init(void) s_log_ctx.global_level, (unsigned long)s_log_ctx.output_mask, s_log_ctx.buffer.capacity); + atomic_store(&s_log_lifecycle_busy, false); + return ESP_OK; } esp_err_t ts_log_deinit(void) { + if (atomic_exchange(&s_log_lifecycle_busy, true)) + return ESP_ERR_INVALID_STATE; if (!s_log_ctx.initialized) { + atomic_store(&s_log_lifecycle_busy, false); return ESP_ERR_INVALID_STATE; } - + xSemaphoreTake(s_log_io_mutex, portMAX_DELAY); xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); - - // 关闭日志文件 - if (s_log_ctx.log_file != NULL) { - fclose(s_log_ctx.log_file); - s_log_ctx.log_file = NULL; - } - - // 释放缓冲区 - if (s_log_ctx.buffer.entries != NULL) { - free(s_log_ctx.buffer.entries); - s_log_ctx.buffer.entries = NULL; - } - - // 释放标签级别列表 - ts_log_tag_level_t *tag = s_log_ctx.tag_levels; - while (tag != NULL) { - ts_log_tag_level_t *next = tag->next; - free(tag); - tag = next; + if (s_log_ctx.active_writers) { + xSemaphoreGive(s_log_ctx.mutex); + xSemaphoreGive(s_log_io_mutex); + atomic_store(&s_log_lifecycle_busy, false); + return ESP_ERR_INVALID_STATE; } + portENTER_CRITICAL(&s_capture_lock); + s_log_ctx.initialized = false; + if (s_log_ctx.esp_log_capture_enabled && s_log_ctx.original_vprintf) + esp_log_set_vprintf(s_log_ctx.original_vprintf); + s_log_ctx.esp_log_capture_enabled = false; + portEXIT_CRITICAL(&s_capture_lock); + ts_log_entry_t *entries = s_log_ctx.buffer.entries; + ts_log_tag_level_t *tags = s_log_ctx.tag_levels; + ts_log_callback_node_t *callbacks = s_log_ctx.callbacks; + s_log_ctx.buffer.entries = NULL; + s_log_ctx.buffer.count = 0; s_log_ctx.tag_levels = NULL; - - // 释放回调列表 - ts_log_callback_node_t *cb = s_log_ctx.callbacks; - while (cb != NULL) { - ts_log_callback_node_t *next = cb->next; - free(cb); - cb = next; - } s_log_ctx.callbacks = NULL; - + FILE *file = s_log_ctx.log_file; + s_log_ctx.log_file = NULL; xSemaphoreGive(s_log_ctx.mutex); - vSemaphoreDelete(s_log_ctx.mutex); - s_log_ctx.mutex = NULL; - - s_log_ctx.initialized = false; + if (file) + fclose(file); + xSemaphoreGive(s_log_io_mutex); + free(entries); + while (tags) { + ts_log_tag_level_t *next = tags->next; + free(tags); + tags = next; + } + while (callbacks) { + ts_log_callback_node_t *next = callbacks->next; + free(callbacks); + callbacks = next; + } + /* Mutex lifetime exceeds all hooks/readers that observed initialized=true. */ + atomic_store(&s_log_lifecycle_busy, false); return ESP_OK; } @@ -319,9 +350,19 @@ void ts_log_v(ts_log_level_t level, const char *tag, const char *format, va_list return; } + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + if (!s_log_ctx.initialized) { + xSemaphoreGive(s_log_ctx.mutex); + return; + } + ++s_log_ctx.active_writers; + xSemaphoreGive(s_log_ctx.mutex); // 检查级别过滤 ts_log_level_t effective_level = get_effective_level(tag); if (level > effective_level) { + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + --s_log_ctx.active_writers; + xSemaphoreGive(s_log_ctx.mutex); return; } @@ -342,19 +383,27 @@ void ts_log_v(ts_log_level_t level, const char *tag, const char *format, va_list } } - vsnprintf(entry.message, TS_LOG_MSG_MAX_LEN, format, args); + va_list preview; + va_copy(preview, args); + int needed = vsnprintf(entry.message, TS_LOG_MSG_MAX_LEN, format, preview); + va_end(preview); + if (ts_log_preview(entry.message, sizeof(entry.message), entry.message, + needed >= TS_LOG_MSG_MAX_LEN)) + atomic_fetch_add(&s_log_ctx.capture_truncated, 1); // 输出到各目标 - xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + xSemaphoreTake(s_log_io_mutex, portMAX_DELAY); if (s_log_ctx.output_mask & TS_LOG_OUTPUT_CONSOLE) { - log_output_console(&entry); + log_output_console(&entry, format, args); } if (s_log_ctx.output_mask & TS_LOG_OUTPUT_FILE) { log_output_file(&entry); } + xSemaphoreGive(s_log_io_mutex); + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); if (s_log_ctx.output_mask & TS_LOG_OUTPUT_BUFFER) { log_output_buffer(&entry); } @@ -363,6 +412,9 @@ void ts_log_v(ts_log_level_t level, const char *tag, const char *format, va_list // 通知回调(在锁外调用) notify_callbacks(&entry); + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + --s_log_ctx.active_writers; + xSemaphoreGive(s_log_ctx.mutex); } void ts_log_hex(ts_log_level_t level, const char *tag, const void *data, size_t length) @@ -523,7 +575,7 @@ esp_err_t ts_log_set_file_path(const char *path) return ESP_ERR_INVALID_ARG; } - xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + xSemaphoreTake(s_log_io_mutex, portMAX_DELAY); // 关闭当前文件 if (s_log_ctx.log_file != NULL) { @@ -535,19 +587,19 @@ esp_err_t ts_log_set_file_path(const char *path) s_log_ctx.file_index = 0; s_log_ctx.file_size = 0; - xSemaphoreGive(s_log_ctx.mutex); + xSemaphoreGive(s_log_io_mutex); return ESP_OK; } esp_err_t ts_log_flush(void) { - xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + xSemaphoreTake(s_log_io_mutex, portMAX_DELAY); if (s_log_ctx.log_file != NULL) { fflush(s_log_ctx.log_file); } - xSemaphoreGive(s_log_ctx.mutex); + xSemaphoreGive(s_log_io_mutex); return ESP_OK; } @@ -567,6 +619,10 @@ size_t ts_log_buffer_get(ts_log_entry_t *entries, size_t max_count, size_t start } xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + if (!s_log_ctx.initialized || !s_log_ctx.buffer.entries) { + xSemaphoreGive(s_log_ctx.mutex); + return 0; + } size_t count = s_log_ctx.buffer.count; if (start_index >= count) { @@ -621,6 +677,14 @@ esp_err_t ts_log_add_callback(ts_log_callback_t callback, node->user_data = user_data; xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + unsigned count = 0; + for (ts_log_callback_node_t *n = s_log_ctx.callbacks; n; n = n->next) + ++count; + if (!s_log_ctx.initialized || count == 8) { + xSemaphoreGive(s_log_ctx.mutex); + free(node); + return ESP_ERR_NO_MEM; + } node->next = s_log_ctx.callbacks; s_log_ctx.callbacks = node; xSemaphoreGive(s_log_ctx.mutex); @@ -646,6 +710,10 @@ esp_err_t ts_log_remove_callback(ts_log_callback_handle_t handle) while (node != NULL) { if (node == target) { + if (node->readers) { + xSemaphoreGive(s_log_ctx.mutex); + return ESP_ERR_INVALID_STATE; + } if (prev == NULL) { s_log_ctx.callbacks = node->next; } else { @@ -724,44 +792,19 @@ const char *ts_log_level_color(ts_log_level_t level) * 私有函数实现 * ========================================================================== */ -static void log_output_console(const ts_log_entry_t *entry) -{ - static const char level_chars[] = { 'N', 'E', 'W', 'I', 'D', 'V' }; - char level_char = (entry->level < TS_LOG_MAX) ? level_chars[entry->level] : '?'; - - if (s_log_ctx.colors_enabled) { - const char *color = ts_log_level_color(entry->level); - - if (s_log_ctx.timestamp_enabled) { - printf("%s%c (%lu) %s: %s%s\n", - color, - level_char, - (unsigned long)entry->timestamp_ms, - entry->tag, - entry->message, - LOG_RESET_COLOR); - } else { - printf("%s%c %s: %s%s\n", - color, - level_char, - entry->tag, - entry->message, - LOG_RESET_COLOR); - } - } else { - if (s_log_ctx.timestamp_enabled) { - printf("%c (%lu) %s: %s\n", - level_char, - (unsigned long)entry->timestamp_ms, - entry->tag, - entry->message); - } else { - printf("%c %s: %s\n", - level_char, - entry->tag, - entry->message); - } - } +static void log_output_console(const ts_log_entry_t *entry, const char *format, va_list args) { + static const char levels[] = "NEWIDV"; + char level = entry->level >= 0 && entry->level < TS_LOG_MAX ? levels[entry->level] : '?'; + const char *color = s_log_ctx.colors_enabled ? ts_log_level_color(entry->level) : ""; + if (s_log_ctx.timestamp_enabled) + printf("%s%c (%lu) %s: ", color, level, (unsigned long)entry->timestamp_ms, entry->tag); + else + printf("%s%c %s: ", color, level, entry->tag); + va_list output; + va_copy(output, args); + vprintf(format, output); + va_end(output); + printf("%s\n", s_log_ctx.colors_enabled ? LOG_RESET_COLOR : ""); } static void log_output_file(const ts_log_entry_t *entry) @@ -814,40 +857,63 @@ static void log_output_buffer(const ts_log_entry_t *entry) if (s_log_ctx.buffer.count < s_log_ctx.buffer.capacity) { s_log_ctx.buffer.count++; + } else { + ++s_log_ctx.logs_dropped; } } +static TaskHandle_t callback_tasks[8]; static void notify_callbacks(const ts_log_entry_t *entry) { + /* Bounded snapshot; removal returns BUSY while its user_data is borrowed. */ + ts_log_callback_node_t *snapshot[8]; + unsigned count = 0; + TaskHandle_t task = xTaskGetCurrentTaskHandle(); + int slot = -1; xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); - - ts_log_callback_node_t *node = s_log_ctx.callbacks; - while (node != NULL) { - if (entry->level <= node->min_level && node->callback != NULL) { - node->callback(entry, node->user_data); + for (unsigned i = 0; i < 8; i++) { + if (callback_tasks[i] == task) { + xSemaphoreGive(s_log_ctx.mutex); + return; + } + if (!callback_tasks[i] && slot < 0) + slot = i; + } + if (slot < 0) { + xSemaphoreGive(s_log_ctx.mutex); + return; + } + callback_tasks[slot] = task; + for (ts_log_callback_node_t *n = s_log_ctx.callbacks; n && count < 8; n = n->next) { + if (entry->level <= n->min_level && n->callback) { + ++n->readers; + snapshot[count++] = n; } - node = node->next; } - + xSemaphoreGive(s_log_ctx.mutex); + for (unsigned i = 0; i < count; ++i) { + snapshot[i]->callback(entry, snapshot[i]->user_data); + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + --snapshot[i]->readers; + xSemaphoreGive(s_log_ctx.mutex); + } + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + callback_tasks[slot] = NULL; xSemaphoreGive(s_log_ctx.mutex); } static ts_log_level_t get_effective_level(const char *tag) { - if (tag == NULL) { - return s_log_ctx.global_level; - } - - // 在锁外快速检查(可能存在竞争,但影响不大) - ts_log_tag_level_t *node = s_log_ctx.tag_levels; - while (node != NULL) { - if (strcmp(node->tag, tag) == 0) { - return node->level; + xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + ts_log_level_t level = s_log_ctx.global_level; + for (ts_log_tag_level_t *n = s_log_ctx.tag_levels; tag && n; n = n->next) { + if (!strcmp(n->tag, tag)) { + level = n->level; + break; } - node = node->next; } - - return s_log_ctx.global_level; + xSemaphoreGive(s_log_ctx.mutex); + return level; } /** @@ -889,14 +955,13 @@ static void rotate_log_file(void) * ESP_LOG 格式: "\033[0;32mI (12345) tag: message\033[0m" * 或无颜色格式: "I (12345) tag: message" */ -static void parse_esp_log_and_store(const char *log_line) -{ +static void parse_esp_log(const char *log_line, ts_log_entry_t *out, bool clipped) { if (log_line == NULL || log_line[0] == '\0') { return; } - ts_log_entry_t entry; - memset(&entry, 0, sizeof(entry)); + ts_log_entry_t *entry = out; + memset(entry, 0, sizeof(*entry)); const char *p = log_line; @@ -909,18 +974,29 @@ static void parse_esp_log_and_store(const char *log_line) // 解析日志级别字符 (E/W/I/D/V) char level_char = *p; switch (level_char) { - case 'E': entry.level = TS_LOG_ERROR; break; - case 'W': entry.level = TS_LOG_WARN; break; - case 'I': entry.level = TS_LOG_INFO; break; - case 'D': entry.level = TS_LOG_DEBUG; break; - case 'V': entry.level = TS_LOG_VERBOSE; break; - default: - // 非标准日志格式,作为 INFO 级别存储 - entry.level = TS_LOG_INFO; - strncpy(entry.tag, "system", TS_LOG_TAG_MAX_LEN - 1); - strncpy(entry.message, log_line, TS_LOG_MSG_MAX_LEN - 1); - entry.timestamp_ms = (uint32_t)(esp_timer_get_time() / 1000); - goto store_entry; + case 'E': + entry->level = TS_LOG_ERROR; + break; + case 'W': + entry->level = TS_LOG_WARN; + break; + case 'I': + entry->level = TS_LOG_INFO; + break; + case 'D': + entry->level = TS_LOG_DEBUG; + break; + case 'V': + entry->level = TS_LOG_VERBOSE; + break; + default: + // 非标准日志格式,作为 INFO 级别存储 + entry->level = TS_LOG_INFO; + strncpy(entry->tag, "system", TS_LOG_TAG_MAX_LEN - 1); + if (ts_log_preview(entry->message, sizeof(entry->message), log_line, clipped)) + atomic_fetch_add(&s_log_ctx.capture_truncated, 1); + entry->timestamp_ms = (uint32_t)(esp_timer_get_time() / 1000); + goto store_entry; } p++; @@ -930,10 +1006,10 @@ static void parse_esp_log_and_store(const char *log_line) // 解析时间戳 (12345) if (*p == '(') { p++; - entry.timestamp_ms = (uint32_t)strtoul(p, (char **)&p, 10); + entry->timestamp_ms = (uint32_t)strtoul(p, (char **)&p, 10); if (*p == ')') p++; } else { - entry.timestamp_ms = (uint32_t)(esp_timer_get_time() / 1000); + entry->timestamp_ms = (uint32_t)(esp_timer_get_time() / 1000); } // 跳过空格 @@ -944,8 +1020,8 @@ static void parse_esp_log_and_store(const char *log_line) while (*p && *p != ':') p++; size_t tag_len = p - tag_start; if (tag_len > 0 && tag_len < TS_LOG_TAG_MAX_LEN) { - strncpy(entry.tag, tag_start, tag_len); - entry.tag[tag_len] = '\0'; + strncpy(entry->tag, tag_start, tag_len); + entry->tag[tag_len] = '\0'; } // 跳过 ": " @@ -955,43 +1031,17 @@ static void parse_esp_log_and_store(const char *log_line) // 剩余部分是消息 const char *msg_start = p; - // 去除尾部的 ANSI 重置码和换行符 - size_t msg_len = strlen(msg_start); - while (msg_len > 0 && (msg_start[msg_len - 1] == '\n' || - msg_start[msg_len - 1] == '\r' || - msg_start[msg_len - 1] == 'm')) { - msg_len--; - // 检查是否是 ANSI 重置码结尾 - if (msg_len >= 3 && msg_start[msg_len - 3] == '\033') { - msg_len -= 3; // 跳过 \033[0 - } - } - - if (msg_len > 0 && msg_len < TS_LOG_MSG_MAX_LEN) { - strncpy(entry.message, msg_start, msg_len); - entry.message[msg_len] = '\0'; - } + if (ts_log_preview(entry->message, sizeof(entry->message), msg_start, clipped)) + atomic_fetch_add(&s_log_ctx.capture_truncated, 1); // 获取当前任务名 TaskHandle_t task = xTaskGetCurrentTaskHandle(); if (task != NULL) { - strncpy(entry.task_name, pcTaskGetName(task), sizeof(entry.task_name) - 1); + strncpy(entry->task_name, pcTaskGetName(task), sizeof(entry->task_name) - 1); } store_entry: - // 存入缓冲区(不需要互斥锁,因为调用者已经在临界区) - if (s_log_ctx.buffer.entries != NULL) { - // 直接写入,不调用 log_output_buffer 避免重复锁 - memcpy(&s_log_ctx.buffer.entries[s_log_ctx.buffer.head], &entry, sizeof(ts_log_entry_t)); - s_log_ctx.buffer.head = (s_log_ctx.buffer.head + 1) % s_log_ctx.buffer.capacity; - if (s_log_ctx.buffer.count < s_log_ctx.buffer.capacity) { - s_log_ctx.buffer.count++; - } - s_log_ctx.total_logs_captured++; - } - - // 通知回调(需要小心,回调中不能再打印日志) - // notify_callbacks(&entry); // 暂时禁用,避免递归 + return; } /** @@ -999,41 +1049,48 @@ static void parse_esp_log_and_store(const char *log_line) */ static int ts_log_vprintf_hook(const char *fmt, va_list args) { - // 临时缓冲区格式化日志 - static char log_buffer[512]; - static bool in_hook = false; // 防止递归 - - // 防止递归调用(某些情况下 vprintf 可能被嵌套调用) - if (in_hook) { - if (s_log_ctx.original_vprintf) { - return s_log_ctx.original_vprintf(fmt, args); + vprintf_like_t output = atomic_load(&s_log_ctx.original_vprintf); + if (!output || output == ts_log_vprintf_hook) + output = vprintf; + va_list console_args; + va_copy(console_args, args); + int result = output(fmt, console_args); + va_end(console_args); + if (!atomic_load(&s_log_ctx.esp_log_capture_enabled)) + return result; + int slot = -1; + portENTER_CRITICAL(&s_capture_lock); + for (unsigned i = 0; i < 2; ++i) + if (!s_capture[i].busy) { + s_capture[i].busy = true; + slot = (int)i; + break; } - return vprintf(fmt, args); - } - - in_hook = true; - - // 格式化日志到缓冲区 - int len = vsnprintf(log_buffer, sizeof(log_buffer), fmt, args); - - // 解析并存储日志(跳过空行) - if (len > 0 && log_buffer[0] != '\n' && log_buffer[0] != '\r') { - // 使用快速锁保护缓冲区访问 - if (s_log_ctx.mutex && xSemaphoreTake(s_log_ctx.mutex, pdMS_TO_TICKS(10)) == pdTRUE) { - parse_esp_log_and_store(log_buffer); + portEXIT_CRITICAL(&s_capture_lock); + if (slot < 0) { + atomic_fetch_add(&s_log_ctx.capture_dropped, 1); + return result; + } + va_list preview_args; + va_copy(preview_args, args); + int len = vsnprintf(s_capture[slot].text, sizeof(s_capture[slot].text), fmt, preview_args); + va_end(preview_args); + if (len > 0) { + parse_esp_log(s_capture[slot].text, &s_capture[slot].entry, + (size_t)len >= sizeof(s_capture[slot].text)); + if (s_log_ctx.mutex && xSemaphoreTake(s_log_ctx.mutex, 0) == pdTRUE) { + if (s_log_ctx.initialized && s_log_ctx.esp_log_capture_enabled) { + log_output_buffer(&s_capture[slot].entry); + ++s_log_ctx.total_logs_captured; + } xSemaphoreGive(s_log_ctx.mutex); - } - } - - in_hook = false; - - // 调用原始 vprintf 输出到控制台 - if (s_log_ctx.original_vprintf) { - // 需要重新创建 va_list,因为已经被消费 - // 直接用已格式化的字符串输出 - return printf("%s", log_buffer); + } else + atomic_fetch_add(&s_log_ctx.capture_dropped, 1); } - return printf("%s", log_buffer); + portENTER_CRITICAL(&s_capture_lock); + s_capture[slot].busy = false; + portEXIT_CRITICAL(&s_capture_lock); + return result; } /* ============================================================================ @@ -1056,6 +1113,8 @@ esp_err_t ts_log_get_stats(ts_log_stats_t *stats) stats->buffer_count = s_log_ctx.buffer.count; stats->total_captured = s_log_ctx.total_logs_captured; stats->dropped = s_log_ctx.logs_dropped; + stats->capture_dropped = atomic_load(&s_log_ctx.capture_dropped); + stats->capture_truncated = atomic_load(&s_log_ctx.capture_truncated); stats->esp_log_capture_enabled = s_log_ctx.esp_log_capture_enabled; xSemaphoreGive(s_log_ctx.mutex); @@ -1071,6 +1130,10 @@ size_t ts_log_buffer_search(ts_log_entry_t *entries, size_t max_count, } xSemaphoreTake(s_log_ctx.mutex, portMAX_DELAY); + if (!s_log_ctx.buffer.entries) { + xSemaphoreGive(s_log_ctx.mutex); + return 0; + } size_t found = 0; size_t count = s_log_ctx.buffer.count; @@ -1118,7 +1181,8 @@ void ts_log_enable_esp_capture(bool enable) return; } - if (enable && !s_log_ctx.esp_log_capture_enabled) { + portENTER_CRITICAL(&s_capture_lock); + if (enable && s_log_ctx.initialized && !s_log_ctx.esp_log_capture_enabled) { // 安装钩子 s_log_ctx.original_vprintf = esp_log_set_vprintf(ts_log_vprintf_hook); s_log_ctx.esp_log_capture_enabled = true; @@ -1129,4 +1193,5 @@ void ts_log_enable_esp_capture(bool enable) } s_log_ctx.esp_log_capture_enabled = false; } + portEXIT_CRITICAL(&s_capture_lock); } diff --git a/components/ts_core/ts_log/src/ts_log_preview.h b/components/ts_core/ts_log/src/ts_log_preview.h new file mode 100644 index 0000000..698b09a --- /dev/null +++ b/components/ts_core/ts_log/src/ts_log_preview.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +#include +/* Fixed UTF-8 prefix; strip complete CSI only. No allocation, no logging. */ +static bool ts_log_preview(char *dst, size_t cap, const char *src, bool clipped) { + size_t n = 0; + while (*src) { + const unsigned char *p = (const unsigned char *)src; + if (p[0] == 27 && p[1] == '[') { + size_t k = 2; + while (p[k] >= 0x20 && p[k] <= 0x3f) + ++k; + if (p[k] >= 0x40 && p[k] <= 0x7e) { + src += k + 1; + continue; + } + } + size_t bytes = + p[0] < 0x80 + ? 1 + : (p[0] >= 0xc2 && p[0] <= 0xdf + ? 2 + : (p[0] >= 0xe0 && p[0] <= 0xef ? 3 + : (p[0] >= 0xf0 && p[0] <= 0xf4 ? 4 : 0))); + bool valid = bytes != 0; + for (size_t i = 1; valid && i < bytes; ++i) + valid = p[i] >= 0x80 && p[i] <= 0xbf; + if (valid && bytes == 3) + valid = !(p[0] == 0xe0 && p[1] < 0xa0) && !(p[0] == 0xed && p[1] >= 0xa0); + if (valid && bytes == 4) + valid = !(p[0] == 0xf0 && p[1] < 0x90) && !(p[0] == 0xf4 && p[1] >= 0x90); + if (!valid) { + clipped = true; + break; + } + if (n + bytes + 1 > cap) { + clipped = true; + break; + } + memcpy(dst + n, src, bytes); + n += bytes; + src += bytes; + } + while (n && (dst[n - 1] == '\r' || dst[n - 1] == '\n')) + --n; + if (clipped && cap >= 5) { + while (n > cap - 5) { + --n; + while (n && ((unsigned char)dst[n] & 0xc0) == 0x80) + --n; + } + memcpy(dst + n, " ...", 4); + n += 4; + } + if (cap) + dst[n] = 0; + return clipped; +} diff --git a/components/ts_core/ts_service/src/ts_service.c b/components/ts_core/ts_service/src/ts_service.c index c1f39aa..3f5b8be 100644 --- a/components/ts_core/ts_service/src/ts_service.c +++ b/components/ts_core/ts_service/src/ts_service.c @@ -143,7 +143,8 @@ esp_err_t ts_service_deinit(void) ESP_LOGI(TAG, "Deinitializing service management..."); // 停止所有服务 - ts_service_stop_all(); + esp_err_t ret = ts_service_stop_all(); + if (ret != ESP_OK) return ret; xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); @@ -380,7 +381,8 @@ esp_err_t ts_service_stop_all(void) if (service->def.phase == phase && service->state == TS_SERVICE_STATE_RUNNING) { xSemaphoreGive(s_svc_ctx.mutex); - ts_service_stop(service); + esp_err_t ret = ts_service_stop(service); + if (ret != ESP_OK) return ret; /* keep dependencies and registry for retry */ xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); } service = service->next; @@ -490,7 +492,8 @@ esp_err_t ts_service_restart(ts_service_handle_t handle) ESP_LOGI(TAG, "Restarting service: %s", service->def.name); esp_err_t ret = ts_service_stop(handle); - if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { + if (ret != ESP_OK && (ret != ESP_ERR_INVALID_STATE || + service->state == TS_SERVICE_STATE_RUNNING)) { return ret; } @@ -910,7 +913,9 @@ static esp_err_t stop_service_internal(ts_service_instance_t *service) if (ret != ESP_OK) { ESP_LOGW(TAG, "Service '%s' stop returned error: %s", service->def.name, esp_err_to_name(ret)); - // 继续停止流程 + /* Failed stop retains the service and its resources for a later retry. */ + set_service_state(service, old_state); + return ret; } } diff --git a/components/ts_https/include/ts_https.h b/components/ts_https/include/ts_https.h index 8f78d34..9c23063 100644 --- a/components/ts_https/include/ts_https.h +++ b/components/ts_https/include/ts_https.h @@ -302,6 +302,19 @@ bool ts_https_role_has_permission(ts_https_role_t user_role, ts_https_role_t req */ httpd_handle_t ts_https_get_handle(void); +/* Published runtime view, copied under a short critical section. No TLS calls in GET. */ +typedef struct { + bool running; + bool require_client_cert; + uint16_t port; + uint32_t loaded_generation; + char loaded_certificate_sha256[65]; + char last_error_stage[24]; + esp_err_t last_error; +} ts_https_runtime_t; +void ts_https_get_runtime(ts_https_runtime_t *out); +void ts_https_record_error(const char *stage, esp_err_t error); + #ifdef __cplusplus } #endif diff --git a/components/ts_https/src/ts_https.c b/components/ts_https/src/ts_https.c index fec639c..86fc1dd 100644 --- a/components/ts_https/src/ts_https.c +++ b/components/ts_https/src/ts_https.c @@ -7,6 +7,9 @@ */ #include "ts_https.h" +#include "ts_cert_time.h" +#include "mbedtls/platform_util.h" +#include "freertos/FreeRTOS.h" #include "ts_https_internal.h" #include "ts_cert.h" #include "esp_https_server.h" @@ -43,6 +46,30 @@ static const char *TAG = "ts_https"; static httpd_handle_t s_server = NULL; static bool s_initialized = false; +static ts_cert_snapshot_t s_material; +static portMUX_TYPE s_runtime_lock = portMUX_INITIALIZER_UNLOCKED; +static ts_https_runtime_t s_runtime = {.port = 443, .require_client_cert = true}; +void ts_https_get_runtime(ts_https_runtime_t *out) +{ + if (!out) return; + portENTER_CRITICAL(&s_runtime_lock); *out = s_runtime; portEXIT_CRITICAL(&s_runtime_lock); +} +void ts_https_record_error(const char *stage, esp_err_t error) +{ + portENTER_CRITICAL(&s_runtime_lock); + s_runtime.last_error = error; + snprintf(s_runtime.last_error_stage, sizeof(s_runtime.last_error_stage), "%s", error == ESP_OK ? "" : stage); + portEXIT_CRITICAL(&s_runtime_lock); +} +static void publish_running(bool running) +{ + portENTER_CRITICAL(&s_runtime_lock); + s_runtime.running = running; + s_runtime.loaded_generation = running ? s_material.generation : 0; + snprintf(s_runtime.loaded_certificate_sha256, sizeof(s_runtime.loaded_certificate_sha256), + "%s", running ? s_material.certificate_sha256 : ""); + portEXIT_CRITICAL(&s_runtime_lock); +} static ts_https_config_t s_config; // Certificate buffers (loaded from ts_cert) @@ -81,22 +108,11 @@ esp_err_t ts_https_init(const ts_https_config_t *config) s_config = (ts_https_config_t)TS_HTTPS_CONFIG_DEFAULT(); } - // Check if PKI is ready - ts_cert_pki_status_t pki_status; - esp_err_t ret = ts_cert_get_status(&pki_status); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to get PKI status: %s", esp_err_to_name(ret)); - return ret; - } - - if (pki_status.status != TS_CERT_STATUS_ACTIVATED) { - ESP_LOGE(TAG, "PKI not activated (status=%d), cannot start HTTPS", - pki_status.status); - return ESP_ERR_INVALID_STATE; - } - - // Load certificates - ret = load_certificates(); + portENTER_CRITICAL(&s_runtime_lock); + s_runtime.port = s_config.port; + s_runtime.require_client_cert = s_config.require_client_cert; + portEXIT_CRITICAL(&s_runtime_lock); + esp_err_t ret = load_certificates(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to load certificates: %s", esp_err_to_name(ret)); return ret; @@ -114,7 +130,7 @@ esp_err_t ts_https_init(const ts_https_config_t *config) void ts_https_deinit(void) { if (s_server) { - ts_https_stop(); + if (ts_https_stop() != ESP_OK) return; } free_certificates(); @@ -130,74 +146,18 @@ void ts_https_deinit(void) static esp_err_t load_certificates(void) { - esp_err_t ret; - - // Allocate buffers - s_server_cert = heap_caps_malloc(TS_CERT_PEM_MAX_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - s_server_key = heap_caps_malloc(TS_CERT_KEY_MAX_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - s_ca_chain = heap_caps_malloc(TS_CERT_CA_CHAIN_MAX_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - - if (!s_server_cert || !s_server_key || !s_ca_chain) { - ESP_LOGE(TAG, "Failed to allocate certificate buffers"); - free_certificates(); - return ESP_ERR_NO_MEM; - } - - // Load server certificate - size_t cert_len = TS_CERT_PEM_MAX_LEN; - ret = ts_cert_get_certificate(s_server_cert, &cert_len); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to load server certificate: %s", esp_err_to_name(ret)); - free_certificates(); - return ret; - } - ESP_LOGI(TAG, "Server certificate loaded (%d bytes)", (int)cert_len); - - // Load private key - size_t key_len = TS_CERT_KEY_MAX_LEN; - ret = ts_cert_get_private_key(s_server_key, &key_len); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to load private key: %s", esp_err_to_name(ret)); - free_certificates(); - return ret; - } - ESP_LOGI(TAG, "Private key loaded (%d bytes)", (int)key_len); - - // Load CA chain (for client certificate verification) - size_t ca_len = TS_CERT_CA_CHAIN_MAX_LEN; - ret = ts_cert_get_ca_chain(s_ca_chain, &ca_len); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "No CA chain loaded: %s", esp_err_to_name(ret)); - // This is okay if we don't require client certs - if (s_config.require_client_cert) { - ESP_LOGE(TAG, "CA chain required for mTLS but not available"); - free_certificates(); - return ret; - } - } else { - ESP_LOGI(TAG, "CA chain loaded (%d bytes)", (int)ca_len); - } - + esp_err_t ret = ts_cert_get_snapshot(s_config.require_client_cert, &s_material); + if (ret != ESP_OK) return ret; + s_server_cert = s_material.certificate; + s_server_key = s_material.key; + s_ca_chain = s_material.ca; return ESP_OK; } static void free_certificates(void) { - if (s_server_cert) { - // Clear sensitive data before freeing - memset(s_server_cert, 0, TS_CERT_PEM_MAX_LEN); - free(s_server_cert); - s_server_cert = NULL; - } - if (s_server_key) { - memset(s_server_key, 0, TS_CERT_KEY_MAX_LEN); - free(s_server_key); - s_server_key = NULL; - } - if (s_ca_chain) { - free(s_ca_chain); - s_ca_chain = NULL; - } + ts_cert_free_snapshot(&s_material); + s_server_cert = s_server_key = s_ca_chain = NULL; } /*===========================================================================*/ @@ -213,7 +173,7 @@ esp_err_t ts_https_start(void) if (s_server) { ESP_LOGW(TAG, "Server already running"); - return ESP_OK; + return ts_https_is_running() ? ESP_OK : ESP_ERR_INVALID_STATE; } // Configure HTTPS server @@ -253,7 +213,7 @@ esp_err_t ts_https_start(void) // Session tickets for faster reconnection config.httpd.enable_so_linger = false; - // Start server + // Retain a failed candidate handle if its stop fails, but do not publish it. esp_err_t ret = httpd_ssl_start(&s_server, &config); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to start HTTPS server: %s", esp_err_to_name(ret)); @@ -268,9 +228,17 @@ esp_err_t ts_https_start(void) .handler = generic_handler, .user_ctx = &s_endpoints[i] }; - httpd_register_uri_handler(s_server, &uri_handler); + ret = httpd_register_uri_handler(s_server, &uri_handler); + if (ret != ESP_OK) { + ts_https_record_error("register_uri", ret); + esp_err_t stop = ts_https_stop(); + if (stop != ESP_OK) ts_https_record_error("cleanup", stop); + return ret; + } } + publish_running(true); + ts_https_record_error("", ESP_OK); ESP_LOGI(TAG, "HTTPS server started on port %d with %d endpoints", s_config.port, s_endpoint_count); @@ -284,7 +252,8 @@ esp_err_t ts_https_stop(void) } esp_err_t ret = httpd_ssl_stop(s_server); - s_server = NULL; + if (ret == ESP_OK) { s_server = NULL; publish_running(false); } + else ts_https_record_error("stop", ret); if (ret == ESP_OK) { ESP_LOGI(TAG, "HTTPS server stopped"); @@ -295,7 +264,9 @@ esp_err_t ts_https_stop(void) bool ts_https_is_running(void) { - return s_server != NULL; + ts_https_runtime_t runtime; + ts_https_get_runtime(&runtime); + return runtime.running; } httpd_handle_t ts_https_get_handle(void) @@ -489,22 +460,13 @@ static void extract_auth_from_cert(const mbedtls_x509_crt *cert, ts_https_auth_t ESP_LOGI(TAG, "Client cert OU='%s' -> role=%s", buf, ts_https_role_to_str(auth->role)); } - // 计算证书有效天数 - // mbedtls_x509_time 包含 year, mon, day, hour, min, sec - // 这里简单估算剩余天数 - time_t now; - time(&now); - struct tm *tm_now = gmtime(&now); - if (tm_now) { - int years_diff = cert->valid_to.year - (tm_now->tm_year + 1900); - int months_diff = cert->valid_to.mon - (tm_now->tm_mon + 1); - int days_diff = cert->valid_to.day - tm_now->tm_mday; - auth->cert_days_remaining = years_diff * 365 + months_diff * 30 + days_diff; - if (auth->cert_days_remaining < 0) { - auth->cert_days_remaining = 0; // 已过期 - } - } - + int64_t expiry; + time_t now = time(NULL); + auth->cert_days_remaining = 0; + if (now != (time_t)-1 && ts_cert_time_utc(cert->valid_to.year, cert->valid_to.mon, + cert->valid_to.day, cert->valid_to.hour, cert->valid_to.min, cert->valid_to.sec, &expiry)) + auth->cert_days_remaining = ts_cert_time_days(expiry - (int64_t)now); + auth->authenticated = true; } diff --git a/components/ts_https/src/ts_https_auth.c b/components/ts_https/src/ts_https_auth.c index b2b240d..18cb093 100644 --- a/components/ts_https/src/ts_https_auth.c +++ b/components/ts_https/src/ts_https_auth.c @@ -1,3 +1,4 @@ +#include "ts_cert_time.h" /** * @file ts_https_auth.c * @brief mTLS Authentication and Role Extraction @@ -134,25 +135,13 @@ esp_err_t ts_https_auth_from_cert(const mbedtls_x509_crt *cert, ts_https_auth_t ESP_LOGW(TAG, "No OU field in certificate, defaulting to viewer"); } - // Calculate days until expiry - // cert->valid_to is mbedtls_x509_time struct - // For simplicity, we'll use a rough calculation + int64_t expiry; time_t now = time(NULL); - struct tm cert_tm = { - .tm_year = cert->valid_to.year - 1900, - .tm_mon = cert->valid_to.mon - 1, - .tm_mday = cert->valid_to.day, - .tm_hour = cert->valid_to.hour, - .tm_min = cert->valid_to.min, - .tm_sec = cert->valid_to.sec - }; - time_t expiry = mktime(&cert_tm); - if (expiry > now) { - auth->cert_days_remaining = (int)((expiry - now) / (24 * 60 * 60)); - } else { - auth->cert_days_remaining = 0; - } - + auth->cert_days_remaining = 0; + if (now != (time_t)-1 && ts_cert_time_utc(cert->valid_to.year, cert->valid_to.mon, + cert->valid_to.day, cert->valid_to.hour, cert->valid_to.min, cert->valid_to.sec, &expiry)) + auth->cert_days_remaining = ts_cert_time_days(expiry - (int64_t)now); + ESP_LOGI(TAG, "Authenticated: %s (%s), role=%s, expires in %d days", auth->username, auth->organization, ts_https_role_to_str(auth->role), diff --git a/components/ts_net/include/ts_http_server.h b/components/ts_net/include/ts_http_server.h index 9e18598..e79d91b 100644 --- a/components/ts_net/include/ts_http_server.h +++ b/components/ts_net/include/ts_http_server.h @@ -123,6 +123,12 @@ esp_err_t ts_http_set_cors(ts_http_request_t *req, const char *origin); */ httpd_handle_t ts_http_server_get_handle(void); +/* Owner hooks: before_stop must drain users; failure preserves the live handle. */ +void ts_http_server_set_stop_hooks(esp_err_t (*before)(httpd_handle_t), + void (*after)(httpd_handle_t)); + +bool ts_http_server_is_stopping(void); + #ifdef __cplusplus } #endif diff --git a/components/ts_net/src/ts_http_server.c b/components/ts_net/src/ts_http_server.c index a8f7726..d411385 100644 --- a/components/ts_net/src/ts_http_server.c +++ b/components/ts_net/src/ts_http_server.c @@ -12,12 +12,30 @@ #include "esp_log.h" #include "esp_heap_caps.h" #include +#include +#include "freertos/task.h" #define TAG "ts_http" #define MAX_ROUTES 64 static httpd_handle_t s_server = NULL; static bool s_initialized = false; +static _Atomic(TaskHandle_t) s_http_task; +static atomic_flag s_stop_busy = ATOMIC_FLAG_INIT; +static atomic_bool s_stopping; +bool ts_http_server_is_stopping(void) { return s_stopping; } +static esp_err_t session_open(httpd_handle_t server, int fd) +{ + (void)server; (void)fd; + s_http_task = xTaskGetCurrentTaskHandle(); + return ESP_OK; +} +static esp_err_t (*s_before_stop)(httpd_handle_t); +static void (*s_after_stop)(httpd_handle_t); +void ts_http_server_set_stop_hooks(esp_err_t (*before)(httpd_handle_t), void (*after)(httpd_handle_t)) +{ + s_before_stop = before; s_after_stop = after; +} // 路由注册表(用于同步到 HTTPS) typedef struct { @@ -26,6 +44,7 @@ typedef struct { ts_http_handler_t handler; void *user_data; // 原始 user_data bool requires_auth; // 认证要求 + ts_http_route_t *owned_copy; /* HTTPD borrows user_ctx; it does not free it. */ } registered_route_t; static registered_route_t s_registered_routes[MAX_ROUTES]; @@ -46,19 +65,22 @@ esp_err_t ts_http_server_init(void) esp_err_t ts_http_server_deinit(void) { - ts_http_server_stop(); + esp_err_t ret = ts_http_server_stop(); + if (ret != ESP_OK) return ret; s_initialized = false; return ESP_OK; } esp_err_t ts_http_server_start(void) { + if (s_stopping) return ESP_ERR_INVALID_STATE; if (s_server) return ESP_OK; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); #ifdef CONFIG_TS_NET_HTTP_PORT config.server_port = CONFIG_TS_NET_HTTP_PORT; #endif + config.open_fn = session_open; config.max_uri_handlers = MAX_ROUTES; config.uri_match_fn = httpd_uri_match_wildcard; config.global_user_ctx = NULL; @@ -81,16 +103,35 @@ esp_err_t ts_http_server_start(void) esp_err_t ts_http_server_stop(void) { - if (!s_server) return ESP_OK; - - httpd_stop(s_server); + if (s_http_task && s_http_task == xTaskGetCurrentTaskHandle()) return ESP_ERR_INVALID_STATE; + if (atomic_flag_test_and_set(&s_stop_busy)) return ESP_ERR_INVALID_STATE; + esp_err_t ret = ESP_OK; + if (!s_server) goto done; + s_stopping = true; + ret = s_before_stop ? s_before_stop(s_server) : ESP_OK; + if (ret != ESP_OK) goto done; + httpd_handle_t stopped = s_server; + ret = httpd_stop(stopped); + if (ret != ESP_OK) goto done; + if (s_after_stop) s_after_stop(stopped); s_server = NULL; + s_http_task = NULL; + s_stopping = false; + for (int i = 0; i < s_route_count; ++i) free(s_registered_routes[i].owned_copy); + memset(s_registered_routes, 0, sizeof(s_registered_routes)); + s_route_count = 0; TS_LOGI(TAG, "HTTP server stopped"); - return ESP_OK; +done: + atomic_flag_clear(&s_stop_busy); + return ret; } static esp_err_t http_handler_wrapper(httpd_req_t *req) { + if(s_stopping && req->method!=HTTP_GET) { + httpd_resp_set_status(req,"503 Service Unavailable"); + return httpd_resp_sendstr(req,"Service is stopping"); + } ts_http_route_t *route = (ts_http_route_t *)req->user_ctx; if (!route || !route->handler) { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "No handler"); @@ -145,7 +186,8 @@ static esp_err_t http_handler_wrapper(httpd_req_t *req) esp_err_t ts_http_server_register_route(const ts_http_route_t *route) { - if (!s_server || !route) return ESP_ERR_INVALID_STATE; + if (!s_server || !route || s_stopping) return ESP_ERR_INVALID_STATE; + if (s_route_count >= MAX_ROUTES) return ESP_ERR_NO_MEM; // Allocate persistent copy of route (prefer PSRAM) ts_http_route_t *route_copy = TS_MALLOC_PSRAM(sizeof(ts_http_route_t)); @@ -173,6 +215,7 @@ esp_err_t ts_http_server_register_route(const ts_http_route_t *route) s_registered_routes[s_route_count].method = route->method; s_registered_routes[s_route_count].handler = route->handler; s_registered_routes[s_route_count].user_data = route->user_data; // 保存 user_data + s_registered_routes[s_route_count].owned_copy = route_copy; s_registered_routes[s_route_count].requires_auth = route->requires_auth; // 保存认证要求 s_route_count++; } diff --git a/components/ts_net/src/ts_time_sync.c b/components/ts_net/src/ts_time_sync.c index f306a0f..df65c9b 100644 --- a/components/ts_net/src/ts_time_sync.c +++ b/components/ts_net/src/ts_time_sync.c @@ -31,6 +31,13 @@ static struct { .ntp_started = false, }; +static void notify_clock_updated(void) +{ + esp_err_t err = ts_event_post(TS_EVENT_BASE_TIME, TS_EVENT_TIME_SYNCED, + &s_time_sync.info, sizeof(s_time_sync.info), 0); + if (err != ESP_OK) ESP_LOGW(TAG, "Time notification lost: %s", esp_err_to_name(err)); +} + /* NTP 同步回调 */ static void time_sync_notification_cb(struct timeval *tv) { @@ -50,8 +57,7 @@ static void time_sync_notification_cb(struct timeval *tv) ESP_LOGI(TAG, "Local time: %s (%s)", strftime_buf, s_time_sync.timezone); /* 发布时间同步完成事件 */ - ts_event_post(TS_EVENT_BASE_TIME, TS_EVENT_TIME_SYNCED, - &s_time_sync.info, sizeof(s_time_sync.info), 0); + notify_clock_updated(); } esp_err_t ts_time_sync_init(const ts_time_sync_config_t *config) @@ -265,6 +271,7 @@ esp_err_t ts_time_sync_set_time(int64_t timestamp_ms, ts_time_source_t source) ESP_LOGI(TAG, "Time set from %s: %s (offset: %lld ms)", source_str, strftime_buf, (long long)(s_time_sync.info.offset_us / 1000)); + notify_clock_updated(); return ESP_OK; } @@ -306,7 +313,7 @@ bool ts_time_sync_needs_sync(void) time_t now; time(&now); struct tm timeinfo; - localtime_r(&now, &timeinfo); + if (now == (time_t)-1 || !gmtime_r(&now, &timeinfo)) return true; /* 如果年份 < 2025,说明系统时间无效(ESP32 默认 1970) */ return (timeinfo.tm_year + 1900) < TS_TIME_MIN_VALID_YEAR; diff --git a/components/ts_pki_client/src/ts_pki_client.c b/components/ts_pki_client/src/ts_pki_client.c index 4a7cad6..38583d5 100644 --- a/components/ts_pki_client/src/ts_pki_client.c +++ b/components/ts_pki_client/src/ts_pki_client.c @@ -11,6 +11,7 @@ * @copyright Copyright (c) 2026 TianShanOS Project */ +#include #include #include #include "freertos/FreeRTOS.h" @@ -39,8 +40,9 @@ static struct { char device_id[TS_CERT_DEVICE_ID_MAX_LEN]; int request_id; // CSR 提交后返回的请求 ID TaskHandle_t enroll_task; + _Atomic bool enroll_running; SemaphoreHandle_t mutex; - bool stop_requested; + _Atomic bool stop_requested; ts_pki_enroll_callback_t callback; void *callback_data; } s_client = {0}; @@ -144,6 +146,8 @@ void ts_pki_client_deinit(void) // 停止后台任务 ts_pki_client_stop_auto_enroll(); + if (s_client.enroll_running) { ESP_LOGW(TAG, "Enrollment still exiting; retaining resources"); return; } + // 释放资源 if (s_client.mutex) { vSemaphoreDelete(s_client.mutex); @@ -207,8 +211,9 @@ esp_err_t ts_pki_client_submit_csr(void) // 检查是否已有有效证书 ts_cert_pki_status_t cert_status; esp_err_t ret = ts_cert_get_status(&cert_status); - if (ret == ESP_OK && cert_status.status == TS_CERT_STATUS_ACTIVATED) { - ESP_LOGI(TAG, "Already have valid certificate"); + if (ret == ESP_OK && (cert_status.has_certificate && cert_status.has_private_key && + cert_status.cert_info.validity != TS_CERT_VALIDITY_EXPIRED)) { + ESP_LOGI(TAG, "Stored certificate retained; no automatic replacement"); return ESP_ERR_INVALID_STATE; } @@ -295,11 +300,17 @@ esp_err_t ts_pki_client_submit_csr(void) ESP_LOGI(TAG, "Certificate auto-issued!"); cJSON *ca_chain = cJSON_GetObjectItem(resp, "ca_chain"); // 安装证书 (mbedtls 需要包含 null 终止符) - ts_cert_install_certificate(cert->valuestring, strlen(cert->valuestring) + 1); + ret = ts_cert_install_certificate(cert->valuestring, strlen(cert->valuestring) + 1); // 安装 CA 链 - if (ca_chain && cJSON_IsString(ca_chain)) { - ts_cert_install_ca_chain(ca_chain->valuestring, strlen(ca_chain->valuestring) + 1); + if (ret == ESP_OK && ca_chain && cJSON_IsString(ca_chain)) { + ret = ts_cert_install_ca_chain(ca_chain->valuestring, strlen(ca_chain->valuestring) + 1); + } + if (ret == ESP_OK) { + ts_cert_pki_status_t installed; + ret = ts_cert_get_status(&installed); + if (ret == ESP_OK && (!installed.has_ca_chain || !installed.ca_valid)) ret = ESP_ERR_INVALID_STATE; } + if (ret != ESP_OK) { cJSON_Delete(resp); return ret; } } cJSON_Delete(resp); } @@ -443,11 +454,15 @@ esp_err_t ts_pki_client_install_certificate(void) // 安装 CA 链 if (ca_chain_str) { ret = ts_cert_install_ca_chain(ca_chain_str, strlen(ca_chain_str) + 1); - if (ret == ESP_OK) { - ESP_LOGI(TAG, "CA chain installed"); + if (ret != ESP_OK) { cJSON_Delete(root); return ret; } + } else { + ts_cert_pki_status_t installed; + ret = ts_cert_get_status(&installed); + if (ret != ESP_OK || (!installed.has_ca_chain || !installed.ca_valid)) { + cJSON_Delete(root); return ESP_ERR_INVALID_STATE; } } - + cJSON_Delete(root); ESP_LOGI(TAG, "Device certificate installed successfully"); @@ -522,7 +537,8 @@ esp_err_t ts_pki_client_start_auto_enroll(ts_pki_enroll_callback_t callback, return ESP_ERR_INVALID_STATE; } - if (s_client.enroll_task) { + bool expected = false; + if (!atomic_compare_exchange_strong(&s_client.enroll_running, &expected, true)) { ESP_LOGW(TAG, "Auto-enroll already running"); return ESP_OK; } @@ -537,6 +553,7 @@ esp_err_t ts_pki_client_start_auto_enroll(ts_pki_enroll_callback_t callback, BaseType_t ret = xTaskCreate(auto_enroll_task, "pki_enroll", 8192, NULL, 5, &s_client.enroll_task); if (ret != pdPASS) { + s_client.enroll_running = false; ESP_LOGE(TAG, "Failed to create enroll task"); return ESP_ERR_NO_MEM; } @@ -547,20 +564,19 @@ esp_err_t ts_pki_client_start_auto_enroll(ts_pki_enroll_callback_t callback, void ts_pki_client_stop_auto_enroll(void) { - if (!s_client.enroll_task) return; + if (!s_client.enroll_running) return; s_client.stop_requested = true; // 等待任务退出 for (int i = 0; i < 50; i++) { - if (!s_client.enroll_task) break; + if (!s_client.enroll_running) break; vTaskDelay(pdMS_TO_TICKS(100)); } - if (s_client.enroll_task) { - ESP_LOGW(TAG, "Force deleting enroll task"); - vTaskDelete(s_client.enroll_task); - s_client.enroll_task = NULL; + if (s_client.enroll_running) { + ESP_LOGW(TAG, "Enrollment cancellation pending; task retains its resources"); + return; } ESP_LOGI(TAG, "Auto-enrollment stopped"); @@ -568,7 +584,7 @@ void ts_pki_client_stop_auto_enroll(void) bool ts_pki_client_is_enrolling(void) { - return s_client.enroll_task != NULL; + return s_client.enroll_running; } /*===========================================================================*/ @@ -694,23 +710,35 @@ static esp_err_t do_http_request(const char *url, esp_http_client_method_t metho return ret; } +static void enroll_wait(uint32_t ms) +{ + while (ms && !s_client.stop_requested) { + uint32_t step = ms < 100 ? ms : 100; + vTaskDelay(pdMS_TO_TICKS(step)); ms -= step; + } +} + static void auto_enroll_task(void *arg) { ESP_LOGI(TAG, "Auto-enrollment task started"); // 等待网络就绪 - vTaskDelay(pdMS_TO_TICKS(5000)); + enroll_wait(5000); + if (s_client.stop_requested) goto done; + // 检查是否已有有效证书 ts_cert_pki_status_t cert_status; if (ts_cert_get_status(&cert_status) == ESP_OK && - cert_status.status == TS_CERT_STATUS_ACTIVATED) { - ESP_LOGI(TAG, "Already have valid certificate, exiting"); + (cert_status.has_certificate && cert_status.has_private_key && + cert_status.cert_info.validity != TS_CERT_VALIDITY_EXPIRED)) { + ESP_LOGI(TAG, "Stored certificate retained; checking readiness"); if (s_client.callback) { - s_client.callback(TS_PKI_ENROLL_APPROVED, "Already enrolled", + s_client.callback(ts_cert_prerequisites(&cert_status, true) ? TS_PKI_ENROLL_APPROVED : TS_PKI_ENROLL_PENDING, + "Credentials already stored; check time and CA readiness", s_client.callback_data); } - s_client.enroll_task = NULL; + s_client.enroll_running = false; vTaskDelete(NULL); return; } @@ -723,12 +751,12 @@ static void auto_enroll_task(void *arg) break; } ESP_LOGW(TAG, "PKI server not reachable, retrying..."); - vTaskDelay(pdMS_TO_TICKS(10000)); + enroll_wait(10000); retry++; } if (s_client.stop_requested) { - s_client.enroll_task = NULL; + s_client.enroll_running = false; vTaskDelete(NULL); return; } @@ -742,7 +770,7 @@ static void auto_enroll_task(void *arg) s_client.callback_data); } // 重试 - vTaskDelay(pdMS_TO_TICKS(60000)); + enroll_wait(60000); } if (s_client.callback) { @@ -765,8 +793,9 @@ static void auto_enroll_task(void *arg) break; } - vTaskDelay(pdMS_TO_TICKS(s_client.config.poll_interval_sec * 1000)); + enroll_wait(s_client.config.poll_interval_sec * 1000); + if (s_client.stop_requested) break; ret = ts_pki_client_check_status(&status); if (ret != ESP_OK) { ESP_LOGW(TAG, "Failed to check status, retrying..."); @@ -823,6 +852,6 @@ static void auto_enroll_task(void *arg) done: ESP_LOGI(TAG, "Auto-enrollment task finished"); - s_client.enroll_task = NULL; + s_client.enroll_running = false; vTaskDelete(NULL); } diff --git a/components/ts_security/CMakeLists.txt b/components/ts_security/CMakeLists.txt index e64f5a7..55e4244 100644 --- a/components/ts_security/CMakeLists.txt +++ b/components/ts_security/CMakeLists.txt @@ -13,6 +13,8 @@ idf_component_register( "src/ts_ssh_hosts_config.c" "src/ts_ssh_commands_config.c" "src/ts_ssh_log_watch.c" + "src/ts_ssh_probe.c" + "src/ts_ssh_service.c" INCLUDE_DIRS "include" REQUIRES diff --git a/components/ts_security/Kconfig b/components/ts_security/Kconfig index 29a7486..b3d15bd 100644 --- a/components/ts_security/Kconfig +++ b/components/ts_security/Kconfig @@ -29,4 +29,12 @@ menu "TianShanOS Security Configuration" default 4 depends on TS_SECURITY_ENABLE + config TS_SSH_LOG_WATCH_MAX + int "Maximum concurrent SSH log watchers" + range 1 32 + default 32 + help + Bounded control slots. Each active watcher uses the existing 8 KiB + task stack; no tasks are allocated for idle slots. + endmenu diff --git a/components/ts_security/include/ts_ssh_client.h b/components/ts_security/include/ts_ssh_client.h index 7cdc107..c26885f 100644 --- a/components/ts_security/include/ts_ssh_client.h +++ b/components/ts_security/include/ts_ssh_client.h @@ -51,6 +51,9 @@ typedef struct { } key; } auth; uint32_t timeout_ms; /**< Connection timeout in ms */ + bool (*cancelled)(void *context); /**< Optional owner cancellation callback */ + void *cancel_context; + size_t max_output_bytes; /**< Per-stream bound, default 64 KiB */ bool verify_host_key; /**< Verify server host key */ } ts_ssh_config_t; @@ -62,7 +65,7 @@ typedef struct { .auth_method = TS_SSH_AUTH_PASSWORD, \ .auth.password = NULL, \ .timeout_ms = 10000, \ - .verify_host_key = false \ + .verify_host_key = true \ } /** Command execution result */ @@ -114,6 +117,11 @@ esp_err_t ts_ssh_session_destroy(ts_ssh_session_t session); * @param session Session handle * @return esp_err_t ESP_OK on success */ +#define TS_SSH_ERR_HOST_UNKNOWN (ESP_ERR_INVALID_STATE + 0x400) +#define TS_SSH_ERR_HOST_CHANGED (ESP_ERR_INVALID_STATE + 0x401) +typedef esp_err_t (*ts_ssh_verify_cb_t)(ts_ssh_session_t session, void *context); +/* Callback is invoked after handshake and BEFORE any user authentication. */ +esp_err_t ts_ssh_connect_with_verifier(ts_ssh_session_t session, ts_ssh_verify_cb_t verify, void *context); esp_err_t ts_ssh_connect(ts_ssh_session_t session); /** diff --git a/components/ts_security/include/ts_ssh_log_watch.h b/components/ts_security/include/ts_ssh_log_watch.h index e1f2ce1..8c343a6 100644 --- a/components/ts_security/include/ts_ssh_log_watch.h +++ b/components/ts_security/include/ts_ssh_log_watch.h @@ -40,6 +40,9 @@ extern "C" { * @brief 日志监测配置 */ typedef struct { + uint32_t run_generation; + bool recovery_only; + char command_id[32]; char host_id[32]; /**< 主机 ID */ char log_file[256]; /**< 日志文件路径(如 /tmp/ts_nohup_xxx.log) */ char ready_pattern[128]; /**< 就绪匹配模式 */ @@ -52,7 +55,11 @@ typedef struct { /** * @brief 监测任务句柄(内部使用) */ -typedef void* ts_ssh_log_watch_handle_t; +typedef uint32_t ts_ssh_log_watch_handle_t; +esp_err_t ts_ssh_log_watch_init(void); +/* Stop requests are asynchronous; false means worker cleanup has completed. */ +bool ts_ssh_log_watch_pending(ts_ssh_log_watch_handle_t handle); +esp_err_t ts_ssh_log_watch_cancel_name(const char *var_name); /*===========================================================================*/ /* Public API */ diff --git a/components/ts_security/include/ts_ssh_probe.h b/components/ts_security/include/ts_ssh_probe.h new file mode 100644 index 0000000..924b4fa --- /dev/null +++ b/components/ts_security/include/ts_ssh_probe.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/* Shell words are always single-quoted; inputs must be NUL terminated. */ +bool ts_ssh_shell_quote(const char *input, char *out, size_t capacity); +bool ts_ssh_log_probe_command(const char *path, const char *ready, const char *fail, + char *out, size_t capacity); +/* Exact protocol token, one optional LF/CRLF; no substring matching. */ +bool ts_ssh_probe_token(const char *output, const char *token); + +#ifdef __cplusplus +} +#endif diff --git a/components/ts_security/include/ts_ssh_service.h b/components/ts_security/include/ts_ssh_service.h new file mode 100644 index 0000000..84ef13a --- /dev/null +++ b/components/ts_security/include/ts_ssh_service.h @@ -0,0 +1,57 @@ +#pragma once +#include "ts_ssh_client.h" +#include "ts_ssh_commands_config.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char state[16], last_known[16], source[16]; + uint32_t generation; + int64_t confirmed_ms; + bool busy; +} ts_ssh_service_status_t; +esp_err_t ts_ssh_service_init(void); +void ts_ssh_service_safe_name(const ts_ssh_command_config_t *cmd, char out[32]); +/* reserve -> probe -> execute -> finish; network calls never hold registry lock */ +esp_err_t ts_ssh_service_begin(const ts_ssh_command_config_t *cmd, ts_ssh_session_t session, + uint32_t *generation); +bool ts_ssh_service_finish(const char *id, uint32_t generation, const char *receipt, ts_ssh_session_t session); +void ts_ssh_service_observe(const char *id, uint32_t generation, const char *state, const char *var_name); +esp_err_t ts_ssh_service_query(const char *id, ts_ssh_service_status_t *out); +esp_err_t ts_ssh_service_stop(const char *id, ts_ssh_service_status_t *out); +/* Conservative guard for mutation; unknown/active command bindings are protected. */ +bool ts_ssh_service_binding_busy(const char *id); +bool ts_ssh_service_launch_command(const ts_ssh_command_config_t *cmd, const char *expanded, + char *out, size_t capacity); + +void ts_ssh_binding_lock(void); +void ts_ssh_binding_unlock(void); +esp_err_t ts_ssh_service_pin(const ts_ssh_command_config_t *cmd, const char *host, uint16_t port, uint32_t *registration); +void ts_ssh_service_unpin(const char *id, uint32_t registration); +bool ts_ssh_service_start_admissible(const char *id); + +bool ts_ssh_service_command_protected(const char *id); +bool ts_ssh_service_host_protected(const char *host_id); + +void ts_ssh_service_cancel_observation(const char *id, uint32_t generation); +bool ts_ssh_service_any_in_use(void); +void ts_ssh_service_set_owner(const char *id, uint32_t registration, const char *rule); +bool ts_ssh_service_rule_protected(const char *rule); +/* Call deletion/forget while holding binding_gate; no network under that gate. */ +esp_err_t ts_ssh_service_delete_begin(const char *id, uint32_t *credential); +void ts_ssh_service_delete_finish(const char *id, uint32_t credential, bool removed); +void ts_ssh_service_forget_stopped(void); +esp_err_t ts_ssh_service_cached(const char *id, ts_ssh_service_status_t *out); +esp_err_t ts_ssh_service_verify_instance(const char *id, uint32_t generation, ts_ssh_session_t session); +bool ts_ssh_service_observation_valid(const char *id, uint32_t generation); +void ts_ssh_service_recovery_kick(const char *id); +bool ts_ssh_service_recover(const char *id, uint32_t generation); +void ts_ssh_service_recovery_done(const char *id, uint32_t generation); + +#ifdef __cplusplus +} +#endif diff --git a/components/ts_security/include/ts_ssh_shell.h b/components/ts_security/include/ts_ssh_shell.h index 8af5053..f88efa0 100644 --- a/components/ts_security/include/ts_ssh_shell.h +++ b/components/ts_security/include/ts_ssh_shell.h @@ -95,20 +95,28 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, ts_ssh_shell_t *shell_out); /** - * @brief Close the shell session + * @brief Consume and release an allocated Shell handle, including EOF/ERROR. + * Caller must clear its handle; a second call with a freed pointer is invalid. + * If channel release would block, locally disconnect its owning SSH session. + * This does not confirm that remote processes have terminated. * * @param shell Shell handle * @return esp_err_t ESP_OK on success */ esp_err_t ts_ssh_shell_close(ts_ssh_shell_t shell); +/** Request local loop exit without freeing the handle or confirming remote exit. + * The caller serializes this with other Shell access and still calls close(). */ +esp_err_t ts_ssh_shell_request_close(ts_ssh_shell_t shell); + /** * @brief Write data to the shell (send to remote) * * @param shell Shell handle * @param data Data to write * @param len Length of data - * @param written Pointer to receive bytes written (optional) + * @param written Bytes accepted by the transport, including partial failure (optional). + * Write/setup waits are bounded; timeout leaves ERROR and must not be replayed. * @return esp_err_t ESP_OK on success */ esp_err_t ts_ssh_shell_write(ts_ssh_shell_t shell, diff --git a/components/ts_security/src/ts_security.c b/components/ts_security/src/ts_security.c index d3bdb02..e31c3b1 100644 --- a/components/ts_security/src/ts_security.c +++ b/components/ts_security/src/ts_security.c @@ -1,3 +1,5 @@ +#include "ts_ssh_log_watch.h" +#include "ts_ssh_service.h" /** * @file ts_security.c * @brief Security Subsystem Implementation @@ -54,6 +56,10 @@ esp_err_t ts_security_init(void) // 非致命错误,继续运行 } + ret = ts_ssh_service_init(); + if (ret != ESP_OK) return ret; + ret = ts_ssh_log_watch_init(); + if (ret != ESP_OK) return ret; s_initialized = true; TS_LOGI(TAG, "Security subsystem initialized"); return ESP_OK; diff --git a/components/ts_security/src/ts_ssh_client.c b/components/ts_security/src/ts_ssh_client.c index 82be18b..8a59d7e 100644 --- a/components/ts_security/src/ts_ssh_client.c +++ b/components/ts_security/src/ts_ssh_client.c @@ -4,31 +4,34 @@ * * This module provides SSH client functionality for TianShanOS, * using libssh2 library for full SSH2 protocol support. - * + * * 会话结构和缓冲区优先分配到 PSRAM */ #include "ts_ssh_client.h" -#include "ts_core.h" /* TS_MALLOC_PSRAM, TS_CALLOC_PSRAM */ #include "esp_log.h" +#include "esp_timer.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "ts_core.h" /* TS_MALLOC_PSRAM, TS_CALLOC_PSRAM */ +#include "ts_known_hosts.h" +#include #include #include -#include -#include #include -#include -#include -#include #include -#include +#include +#include +#include +#include #include +#include #include +#include #include -#include +#include static const char *TAG = "ts_ssh"; @@ -38,15 +41,16 @@ static const char *TAG = "ts_ssh"; /** SSH 会话内部结构 */ struct ts_ssh_session_s { - ts_ssh_config_t config; /**< 会话配置 */ - ts_ssh_state_t state; /**< 当前状态 */ - int sock; /**< Socket 文件描述符 */ - LIBSSH2_SESSION *session; /**< libssh2 会话句柄 */ - char error_msg[256]; /**< 最后的错误消息 */ - char *host_copy; /**< 主机地址副本 */ - char *username_copy; /**< 用户名副本 */ - char *password_copy; /**< 密码副本 */ - volatile bool abort_flag; /**< 中止标志 */ + ts_ssh_config_t config; /**< 会话配置 */ + ts_ssh_state_t state; /**< 当前状态 */ + int sock; /**< Socket 文件描述符 */ + LIBSSH2_SESSION *session; /**< libssh2 会话句柄 */ + char error_msg[256]; /**< 最后的错误消息 */ + char *host_copy; /**< 主机地址副本 */ + char *username_copy; /**< 用户名副本 */ + char *password_copy; /**< 密码副本 */ + atomic_bool abort_flag; + int64_t deadline_us; /**< 中止标志 */ }; /** 全局初始化标志 */ @@ -59,39 +63,45 @@ static bool s_initialized = false; /** * @brief 等待 socket 可读/可写 */ -static int wait_socket(int sock, LIBSSH2_SESSION *session, int timeout_ms) -{ - struct timeval timeout; - fd_set fd; - fd_set *readfd = NULL; - fd_set *writefd = NULL; - int dir; - - timeout.tv_sec = timeout_ms / 1000; - timeout.tv_usec = (timeout_ms % 1000) * 1000; - - FD_ZERO(&fd); - FD_SET(sock, &fd); - - /* 获取 libssh2 需要等待的方向 */ - dir = libssh2_session_block_directions(session); - - if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) { - readfd = &fd; - } - - if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) { - writefd = &fd; - } +static bool operation_expired(ts_ssh_session_t s) { + return atomic_load(&s->abort_flag) || + (s->config.cancelled && s->config.cancelled(s->config.cancel_context)) || + esp_timer_get_time() >= s->deadline_us; +} - return select(sock + 1, readfd, writefd, NULL, &timeout); +static int wait_socket(ts_ssh_session_t s) { + if (operation_expired(s)) + return -1; + int64_t left = s->deadline_us - esp_timer_get_time(); + if (left > 100000) + left = 100000; + if (left <= 0) + return -1; + struct timeval timeout = {.tv_sec = 0, .tv_usec = left}; + fd_set rd, wr; + FD_ZERO(&rd); + FD_ZERO(&wr); + int dir = + s->session ? libssh2_session_block_directions(s->session) : LIBSSH2_SESSION_BLOCK_OUTBOUND; + if (!dir) + dir = LIBSSH2_SESSION_BLOCK_INBOUND; + if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) + FD_SET(s->sock, &rd); + if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) + FD_SET(s->sock, &wr); + int rc = select(s->sock + 1, &rd, &wr, NULL, &timeout); + return (rc < 0 && errno != EINTR) || operation_expired(s) ? -1 : rc; } +/* Teardown cannot wait for a remote peer. These callbacks make all remaining + * libssh2 channel cleanup observe a disconnected transport (never EAGAIN). */ +static LIBSSH2_RECV_FUNC(closed_recv) { return 0; } +static LIBSSH2_SEND_FUNC(closed_send) { return -ENOTCONN; } + /** * @brief 设置错误消息 */ -static void set_error(ts_ssh_session_t session, const char *fmt, ...) -{ +static void set_error(ts_ssh_session_t session, const char *fmt, ...) { va_list args; va_start(args, fmt); vsnprintf(session->error_msg, sizeof(session->error_msg), fmt, args); @@ -102,8 +112,7 @@ static void set_error(ts_ssh_session_t session, const char *fmt, ...) /** * @brief 复制字符串 */ -static char *strdup_safe(const char *str) -{ +static char *strdup_safe(const char *str) { if (str == NULL) { return NULL; } @@ -118,8 +127,7 @@ static char *strdup_safe(const char *str) * 公开 API 实现 * ============================================================================ */ -esp_err_t ts_ssh_client_init(void) -{ +esp_err_t ts_ssh_client_init(void) { if (s_initialized) { return ESP_OK; } @@ -135,8 +143,7 @@ esp_err_t ts_ssh_client_init(void) return ESP_OK; } -esp_err_t ts_ssh_client_deinit(void) -{ +esp_err_t ts_ssh_client_deinit(void) { if (!s_initialized) { return ESP_OK; } @@ -147,8 +154,7 @@ esp_err_t ts_ssh_client_deinit(void) return ESP_OK; } -esp_err_t ts_ssh_session_create(const ts_ssh_config_t *config, ts_ssh_session_t *session_out) -{ +esp_err_t ts_ssh_session_create(const ts_ssh_config_t *config, ts_ssh_session_t *session_out) { if (!config || !session_out) { return ESP_ERR_INVALID_ARG; } @@ -176,7 +182,8 @@ esp_err_t ts_ssh_session_create(const ts_ssh_config_t *config, ts_ssh_session_t session->config = *config; session->config.port = config->port ? config->port : 22; session->config.timeout_ms = config->timeout_ms ? config->timeout_ms : 10000; - + + atomic_init(&session->abort_flag, false); /* 复制字符串(因为调用者可能释放原始字符串) */ session->host_copy = strdup_safe(config->host); session->username_copy = strdup_safe(config->username); @@ -188,19 +195,27 @@ esp_err_t ts_ssh_session_create(const ts_ssh_config_t *config, ts_ssh_session_t session->config.auth.password = session->password_copy; } + if (!session->host_copy || !session->username_copy || + (config->auth_method == TS_SSH_AUTH_PASSWORD && config->auth.password && + !session->password_copy)) { + free(session->host_copy); + free(session->username_copy); + free(session->password_copy); + free(session); + return ESP_ERR_NO_MEM; + } session->sock = -1; session->session = NULL; session->state = TS_SSH_STATE_DISCONNECTED; session->error_msg[0] = '\0'; *session_out = session; - ESP_LOGD(TAG, "Session created for %s@%s:%d", - session->config.username, session->config.host, session->config.port); + ESP_LOGD(TAG, "Session created for %s@%s:%d", session->config.username, session->config.host, + session->config.port); return ESP_OK; } -esp_err_t ts_ssh_session_destroy(ts_ssh_session_t session) -{ +esp_err_t ts_ssh_session_destroy(ts_ssh_session_t session) { if (!session) { return ESP_ERR_INVALID_ARG; } @@ -220,641 +235,260 @@ esp_err_t ts_ssh_session_destroy(ts_ssh_session_t session) return ESP_OK; } -esp_err_t ts_ssh_connect(ts_ssh_session_t session) -{ - if (!session) { - return ESP_ERR_INVALID_ARG; - } - - if (session->state == TS_SSH_STATE_CONNECTED) { - return ESP_OK; /* 已连接 */ - } - - session->state = TS_SSH_STATE_CONNECTING; - - /* 解析主机地址 */ - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(session->config.port); - sin.sin_addr.s_addr = inet_addr(session->config.host); - - /* 如果不是有效的 IP 地址,尝试 DNS 解析 */ - if (sin.sin_addr.s_addr == INADDR_NONE) { - struct hostent *hp = gethostbyname(session->config.host); - if (hp == NULL) { - set_error(session, "Failed to resolve host: %s", session->config.host); - session->state = TS_SSH_STATE_ERROR; - return ESP_FAIL; - } - memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); - } +esp_err_t ts_ssh_connect(ts_ssh_session_t s) { return ts_ssh_connect_with_verifier(s, NULL, NULL); } - /* 创建 socket */ - session->sock = socket(AF_INET, SOCK_STREAM, 0); - if (session->sock < 0) { - set_error(session, "Failed to create socket: %s", strerror(errno)); - session->state = TS_SSH_STATE_ERROR; - return ESP_FAIL; - } - - /* 设置 socket 超时 */ - struct timeval tv; - tv.tv_sec = session->config.timeout_ms / 1000; - tv.tv_usec = (session->config.timeout_ms % 1000) * 1000; - setsockopt(session->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - setsockopt(session->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - - /* 连接 */ - ESP_LOGI(TAG, "Connecting to %s:%d...", session->config.host, session->config.port); - if (connect(session->sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) { - set_error(session, "Failed to connect: %s", strerror(errno)); - close(session->sock); - session->sock = -1; - session->state = TS_SSH_STATE_ERROR; - return ESP_FAIL; - } - - /* 创建 libssh2 会话 */ - session->session = libssh2_session_init(); - if (!session->session) { - set_error(session, "Failed to create SSH session"); - close(session->sock); - session->sock = -1; - session->state = TS_SSH_STATE_ERROR; - return ESP_FAIL; - } - - /* 设置非阻塞模式 */ - libssh2_session_set_blocking(session->session, 0); - - /* 执行 SSH 握手 */ - int rc; - while ((rc = libssh2_session_handshake(session->session, session->sock)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - - if (rc != 0) { - char *err_msg = NULL; - libssh2_session_last_error(session->session, &err_msg, NULL, 0); - set_error(session, "SSH handshake failed: %s (rc=%d)", err_msg ? err_msg : "unknown", rc); - libssh2_session_free(session->session); - session->session = NULL; - close(session->sock); - session->sock = -1; - session->state = TS_SSH_STATE_ERROR; - return ESP_FAIL; - } - - ESP_LOGD(TAG, "SSH handshake completed"); - session->state = TS_SSH_STATE_AUTHENTICATING; - - /* 执行认证 */ - if (session->config.auth_method == TS_SSH_AUTH_PASSWORD) { - /* 密码认证 */ - ESP_LOGD(TAG, "Authenticating with password..."); - while ((rc = libssh2_userauth_password(session->session, - session->config.username, - session->config.auth.password)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - } else { - /* 公钥认证 */ - - /* 首先检查服务器支持的认证方法(需要处理 EAGAIN) */ - char *userauthlist = NULL; - do { - userauthlist = libssh2_userauth_list(session->session, - session->config.username, - strlen(session->config.username)); - if (!userauthlist) { - int err = libssh2_session_last_errno(session->session); - if (err == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - continue; - } - /* 其他错误或已认证 */ - break; - } - } while (!userauthlist); - - if (userauthlist) { - ESP_LOGI(TAG, "Server authentication methods: %s", userauthlist); - if (!strstr(userauthlist, "publickey")) { - ESP_LOGW(TAG, "Server does not support publickey authentication!"); - } - } - - /* 优先使用文件路径方式(更可靠) */ - if (session->config.auth.key.private_key_path) { - const char *key_path = session->config.auth.key.private_key_path; - ESP_LOGI(TAG, "Authenticating with public key from file: %s", key_path); - - /* 验证文件存在且可读 */ - FILE *f = fopen(key_path, "r"); - if (!f) { - ESP_LOGE(TAG, "Cannot open private key file: %s (errno=%d)", key_path, errno); - set_error(session, "Cannot open private key file"); - libssh2_session_disconnect(session->session, "Key file error"); - libssh2_session_free(session->session); - session->session = NULL; - close(session->sock); - session->sock = -1; - session->state = TS_SSH_STATE_ERROR; - return ESP_ERR_NOT_FOUND; - } - - /* 读取并打印前 64 字节用于调试 */ - char header[65] = {0}; - size_t read_len = fread(header, 1, 64, f); - fseek(f, 0, SEEK_END); - long file_size = ftell(f); - fclose(f); - (void)read_len; /* 抑制未使用警告 */ - - ESP_LOGI(TAG, "Key file size: %ld bytes, header: %.40s...", file_size, header); - - /* 构造公钥文件路径 (私钥路径 + ".pub") */ - char pubkey_path[128]; - snprintf(pubkey_path, sizeof(pubkey_path), "%s.pub", key_path); - - /* 检查公钥文件是否存在 */ - const char *pubkey_ptr = NULL; - FILE *pub_f = fopen(pubkey_path, "r"); - if (pub_f) { - fclose(pub_f); - pubkey_ptr = pubkey_path; - ESP_LOGI(TAG, "Using public key file: %s", pubkey_path); - } else { - ESP_LOGW(TAG, "Public key file not found: %s (will derive from private key)", pubkey_path); - } - - /* 清除之前的错误状态 */ - libssh2_session_set_last_error(session->session, 0, NULL); - - while ((rc = libssh2_userauth_publickey_fromfile_ex( - session->session, - session->config.username, strlen(session->config.username), - pubkey_ptr, /* 公钥路径(如果存在) */ - key_path, - session->config.auth.key.passphrase)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - - if (rc != 0) { - char *err_msg = NULL; - int err_len = 0; - int err_code = libssh2_session_last_error(session->session, &err_msg, &err_len, 0); - ESP_LOGE(TAG, "libssh2_userauth_publickey_fromfile_ex failed: rc=%d, err_code=%d, err=%s", - rc, err_code, err_msg ? err_msg : "(null)"); - - /* 尝试使用 libssh2_userauth_publickey 回调方式 */ - ESP_LOGI(TAG, "Trying alternative authentication method..."); - } - } - /* 回退到内存方式 */ - else if (session->config.auth.key.private_key && - session->config.auth.key.private_key_len > 0) { - ESP_LOGI(TAG, "Authenticating with public key from memory (key_len=%zu)...", - session->config.auth.key.private_key_len); - - /* 打印私钥头部用于调试 */ - const char *key_data = (const char *)session->config.auth.key.private_key; - size_t key_len = session->config.auth.key.private_key_len; - ESP_LOGI(TAG, "Private key header: %.50s", key_data); - ESP_LOGI(TAG, "Private key length: %zu", key_len); - - /* 检查 PEM 格式 */ - if (strstr(key_data, "-----BEGIN RSA PRIVATE KEY-----")) { - ESP_LOGI(TAG, "Key type: RSA (PKCS#1)"); - } else if (strstr(key_data, "-----BEGIN EC PRIVATE KEY-----")) { - ESP_LOGI(TAG, "Key type: EC (ECDSA) - Note: libssh2 mbedTLS backend may not support ECDSA frommemory"); - } else if (strstr(key_data, "-----BEGIN PRIVATE KEY-----")) { - ESP_LOGI(TAG, "Key type: PKCS#8 - May require conversion to PKCS#1"); - } else if (strstr(key_data, "-----BEGIN OPENSSH PRIVATE KEY-----")) { - ESP_LOGE(TAG, "Key type: OpenSSH - NOT SUPPORTED! Please use PEM format (ssh-keygen -m PEM)"); - } else { - ESP_LOGW(TAG, "Key type: Unknown format"); - } - - /* - * libssh2_userauth_publickey_frommemory 内部需要获取认证方法列表 - * 如果之前没有调用过 libssh2_userauth_list,需要先调用一次 - * 确保 session 处于正确的状态 - */ - if (!userauthlist) { - do { - userauthlist = libssh2_userauth_list(session->session, - session->config.username, - strlen(session->config.username)); - if (!userauthlist) { - int err = libssh2_session_last_errno(session->session); - if (err == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - continue; - } - break; - } - } while (!userauthlist); - - if (userauthlist) { - ESP_LOGI(TAG, "Server authentication methods: %s", userauthlist); - } - } - - /* 清除之前的错误状态 */ - libssh2_session_set_last_error(session->session, 0, NULL); - - while ((rc = libssh2_userauth_publickey_frommemory( - session->session, - session->config.username, strlen(session->config.username), - NULL, 0, /* 公钥数据(可选) */ - (const char *)session->config.auth.key.private_key, - session->config.auth.key.private_key_len, - session->config.auth.key.passphrase)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - - if (rc != 0) { - char *err_msg = NULL; - int err_len = 0; - int err_code = libssh2_session_last_error(session->session, &err_msg, &err_len, 0); - ESP_LOGE(TAG, "libssh2_userauth_publickey_frommemory failed:"); - ESP_LOGE(TAG, " rc=%d, err_code=%d, err_msg=%s", - rc, err_code, err_msg ? err_msg : "(null)"); - - /* 提供更友好的错误提示 */ - if (rc == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) { - ESP_LOGE(TAG, " Hint: Server rejected the public key. Check if key is authorized on server."); - } else if (rc == LIBSSH2_ERROR_FILE) { - ESP_LOGE(TAG, " Hint: Key format error. Make sure key is in PEM format (not OpenSSH format)."); - } else if (rc == LIBSSH2_ERROR_METHOD_NONE) { - ESP_LOGE(TAG, " Hint: No handler for this key type. Try RSA key instead of ECDSA."); - } else if (rc == -1 && (!err_msg || strlen(err_msg) == 0)) { - ESP_LOGE(TAG, " Hint: Unknown error (-1). Possible causes:"); - ESP_LOGE(TAG, " 1. Key format not supported (try RSA instead of ECDSA)"); - ESP_LOGE(TAG, " 2. Key parsing failed (check PEM format)"); - ESP_LOGE(TAG, " 3. mbedTLS backend limitation"); - } +esp_err_t ts_ssh_connect_with_verifier(ts_ssh_session_t s, ts_ssh_verify_cb_t verify, + void *context) { + if (!s) + return ESP_ERR_INVALID_ARG; + if (s->state == TS_SSH_STATE_CONNECTED) + return ESP_OK; + if (s->session || s->sock >= 0) + ts_ssh_disconnect(s); + s->deadline_us = esp_timer_get_time() + (int64_t)s->config.timeout_ms * 1000; + s->state = TS_SSH_STATE_CONNECTING; + esp_err_t ret = ESP_FAIL; + struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(s->config.port)}; + if (inet_pton(AF_INET, s->config.host, &addr.sin_addr) != 1) { + /* lwIP DNS is synchronous; cancellation is observed immediately after + * its configured resolver timeout. No extra resolver task is created. */ + struct hostent *host = gethostbyname(s->config.host); + if (!host || host->h_length != sizeof(addr.sin_addr)) + goto failed; + memcpy(&addr.sin_addr, host->h_addr, sizeof(addr.sin_addr)); + } + if (operation_expired(s)) + goto timeout; + s->sock = socket(AF_INET, SOCK_STREAM, 0); + if (s->sock < 0 || fcntl(s->sock, F_SETFL, O_NONBLOCK) < 0) + goto failed; + int rc = connect(s->sock, (struct sockaddr *)&addr, sizeof(addr)); + if (rc && errno != EINPROGRESS) + goto failed; + while (rc) { + int ready = wait_socket(s); + if (ready < 0) + goto timeout; + if (!ready) + continue; + int error = 0; + socklen_t size = sizeof(error); + if (getsockopt(s->sock, SOL_SOCKET, SO_ERROR, &error, &size) || error) + goto failed; + break; + } + s->session = libssh2_session_init(); + if (!s->session) { + ret = ESP_ERR_NO_MEM; + goto failed; + } + libssh2_session_set_blocking(s->session, 0); + while ((rc = libssh2_session_handshake(s->session, s->sock)) == LIBSSH2_ERROR_EAGAIN) + if (wait_socket(s) < 0) + goto timeout; + if (rc) + goto failed; + if (verify) + ret = verify(s, context); + else { + ts_host_verify_result_t status; + ret = ts_known_hosts_verify(s, &status, NULL); + if (ret == ESP_OK && status != TS_HOST_VERIFY_OK) + ret = status == TS_HOST_VERIFY_NOT_FOUND ? TS_SSH_ERR_HOST_UNKNOWN + : status == TS_HOST_VERIFY_MISMATCH ? TS_SSH_ERR_HOST_CHANGED + : ESP_FAIL; + } + if (ret != ESP_OK) + goto failed; + if (operation_expired(s)) + goto timeout; + s->state = TS_SSH_STATE_AUTHENTICATING; + do { + if (s->config.auth_method == TS_SSH_AUTH_PASSWORD) { + if (!s->config.auth.password) { + ret = ESP_ERR_INVALID_ARG; + goto failed; } + rc = libssh2_userauth_password(s->session, s->config.username, s->config.auth.password); + } else if (s->config.auth.key.private_key_path) { + rc = libssh2_userauth_publickey_fromfile_ex( + s->session, s->config.username, strlen(s->config.username), NULL, + s->config.auth.key.private_key_path, s->config.auth.key.passphrase); + } else if (s->config.auth.key.private_key && s->config.auth.key.private_key_len) { + rc = libssh2_userauth_publickey_frommemory( + s->session, s->config.username, strlen(s->config.username), NULL, 0, + (const char *)s->config.auth.key.private_key, s->config.auth.key.private_key_len, + s->config.auth.key.passphrase); } else { - set_error(session, "No private key provided (path or memory)"); - libssh2_session_disconnect(session->session, "No key data"); - libssh2_session_free(session->session); - session->session = NULL; - close(session->sock); - session->sock = -1; - session->state = TS_SSH_STATE_ERROR; - return ESP_ERR_INVALID_ARG; + ret = ESP_ERR_INVALID_ARG; + goto failed; } - } - - if (rc != 0) { - char *err_msg = NULL; - libssh2_session_last_error(session->session, &err_msg, NULL, 0); - set_error(session, "Authentication failed: %s (rc=%d)", err_msg ? err_msg : "unknown", rc); - libssh2_session_disconnect(session->session, "Authentication failed"); - libssh2_session_free(session->session); - session->session = NULL; - close(session->sock); - session->sock = -1; - session->state = TS_SSH_STATE_ERROR; - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGI(TAG, "Connected and authenticated to %s@%s", - session->config.username, session->config.host); - session->state = TS_SSH_STATE_CONNECTED; + if (rc == LIBSSH2_ERROR_EAGAIN && wait_socket(s) < 0) + goto timeout; + } while (rc == LIBSSH2_ERROR_EAGAIN); + if (rc) { + ret = ESP_ERR_INVALID_STATE; + goto failed; + } + if (operation_expired(s)) + goto timeout; + s->state = TS_SSH_STATE_CONNECTED; return ESP_OK; +timeout: + ret = ESP_ERR_TIMEOUT; +failed: + if (ret == ESP_OK) + ret = ESP_FAIL; + set_error(s, "SSH connection failed (code=%d)", ret); + ts_ssh_disconnect(s); + s->state = TS_SSH_STATE_ERROR; + return ret; } -esp_err_t ts_ssh_disconnect(ts_ssh_session_t session) -{ - if (!session) { +esp_err_t ts_ssh_disconnect(ts_ssh_session_t s) { + if (!s) return ESP_ERR_INVALID_ARG; + if (s->session) { + libssh2_session_callback_set(s->session, LIBSSH2_CALLBACK_RECV, (void *)closed_recv); + libssh2_session_callback_set(s->session, LIBSSH2_CALLBACK_SEND, (void *)closed_send); + libssh2_session_free(s->session); + s->session = NULL; } - - if (session->session) { - libssh2_session_disconnect(session->session, "Normal shutdown"); - libssh2_session_free(session->session); - session->session = NULL; - } - - if (session->sock >= 0) { - close(session->sock); - session->sock = -1; + if (s->sock >= 0) { + close(s->sock); + s->sock = -1; } - - session->state = TS_SSH_STATE_DISCONNECTED; - ESP_LOGD(TAG, "Disconnected"); + s->state = TS_SSH_STATE_DISCONNECTED; return ESP_OK; } -bool ts_ssh_is_connected(ts_ssh_session_t session) -{ +bool ts_ssh_is_connected(ts_ssh_session_t session) { return session && session->state == TS_SSH_STATE_CONNECTED; } -ts_ssh_state_t ts_ssh_get_state(ts_ssh_session_t session) -{ +ts_ssh_state_t ts_ssh_get_state(ts_ssh_session_t session) { return session ? session->state : TS_SSH_STATE_DISCONNECTED; } -esp_err_t ts_ssh_exec(ts_ssh_session_t session, const char *command, ts_ssh_exec_result_t *result) -{ - if (!session || !command || !result) { +static esp_err_t exec_command(ts_ssh_session_t s, const char *command, ts_ssh_output_cb_t callback, + void *context, ts_ssh_exec_result_t *result, int *exit_code) { + if (!s || !command || (!callback && !result)) return ESP_ERR_INVALID_ARG; - } - - if (session->state != TS_SSH_STATE_CONNECTED) { - set_error(session, "Not connected"); + if (!ts_ssh_is_connected(s)) return ESP_ERR_INVALID_STATE; + if (result) { + memset(result, 0, sizeof(*result)); + result->exit_code = -1; } - - memset(result, 0, sizeof(ts_ssh_exec_result_t)); - result->exit_code = -1; - - /* 打开通道 */ + if (exit_code) + *exit_code = -1; + s->deadline_us = esp_timer_get_time() + (int64_t)s->config.timeout_ms * 1000; + esp_err_t ret = ESP_FAIL; LIBSSH2_CHANNEL *channel = NULL; int rc; - - while ((channel = libssh2_channel_open_session(session->session)) == NULL && - libssh2_session_last_error(session->session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - - if (!channel) { - char *err_msg = NULL; - libssh2_session_last_error(session->session, &err_msg, NULL, 0); - set_error(session, "Failed to open channel: %s", err_msg ? err_msg : "unknown"); - return ESP_FAIL; - } - - /* 执行命令 */ - ESP_LOGD(TAG, "Executing: %s", command); - while ((rc = libssh2_channel_exec(channel, command)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - - if (rc != 0) { - set_error(session, "Failed to exec command: rc=%d", rc); - libssh2_channel_free(channel); - return ESP_FAIL; - } - - /* 读取输出 */ - size_t stdout_capacity = 4096; - size_t stderr_capacity = 1024; - result->stdout_data = TS_MALLOC_PSRAM(stdout_capacity); - result->stderr_data = TS_MALLOC_PSRAM(stderr_capacity); - - if (!result->stdout_data || !result->stderr_data) { - free(result->stdout_data); - free(result->stderr_data); - result->stdout_data = NULL; - result->stderr_data = NULL; - libssh2_channel_free(channel); - return ESP_ERR_NO_MEM; - } - - result->stdout_len = 0; - result->stderr_len = 0; - - /* 循环读取直到 channel EOF。 - * 内层 do-while 批量 drain 当前所有可用数据(rc > 0 时持续读)。 - * 外层用 libssh2_channel_eof() 判断是否结束。 - * 原来的 bug:drain 后 rc==0,走 else break 过早退出,丢失后续数据。 - * 安全措施:非 EAGAIN 错误立即返回,防止无限循环;最多等 300 轮(约 5 分钟)。 */ - int wait_rounds = 0; + while (!operation_expired(s)) { + channel = libssh2_channel_open_session(s->session); + if (channel) + break; + if (libssh2_session_last_errno(s->session) != LIBSSH2_ERROR_EAGAIN) + goto failed; + if (wait_socket(s) < 0) + goto timeout; + } + if (!channel || operation_expired(s)) + goto timeout; + while ((rc = libssh2_channel_exec(channel, command)) == LIBSSH2_ERROR_EAGAIN) + if (wait_socket(s) < 0) + goto timeout; + if (rc) + goto failed; + size_t capacity[2] = {0, 0}; + size_t limit = s->config.max_output_bytes ? s->config.max_output_bytes : 65536; for (;;) { - char buffer[512]; - int got_data = 0; - - /* Drain stdout —— 一次性读完当前所有可用数据 */ - do { - rc = libssh2_channel_read(channel, buffer, sizeof(buffer)); + bool got_data = false; + for (int stream = 0; stream < 2; stream++) { + /* One bounded chunk per stream prevents stdout starving stderr/cancel. */ + if (operation_expired(s)) + goto timeout; + char buffer[512]; + rc = libssh2_channel_read_ex(channel, stream ? SSH_EXTENDED_DATA_STDERR : 0, buffer, + sizeof(buffer)); + if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) + goto failed; if (rc > 0) { - got_data = 1; - while (result->stdout_len + rc >= stdout_capacity) { - stdout_capacity *= 2; - char *new_buf = TS_REALLOC_PSRAM(result->stdout_data, stdout_capacity); - if (!new_buf) { - set_error(session, "Out of memory"); - ts_ssh_exec_result_free(result); - libssh2_channel_free(channel); - return ESP_ERR_NO_MEM; + got_data = true; + if (callback) + callback(buffer, rc, stream != 0, context); + if (result) { + char **data = stream ? &result->stderr_data : &result->stdout_data; + size_t *len = stream ? &result->stderr_len : &result->stdout_len; + if ((size_t)rc > limit - *len) { + ret = ESP_ERR_INVALID_SIZE; + goto failed; } - result->stdout_data = new_buf; - } - memcpy(result->stdout_data + result->stdout_len, buffer, rc); - result->stdout_len += rc; - } else if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { - set_error(session, "Channel read error: %d", rc); - ts_ssh_exec_result_free(result); - libssh2_channel_free(channel); - return ESP_FAIL; - } - } while (rc > 0); - - /* Drain stderr —— 同理 */ - do { - rc = libssh2_channel_read_stderr(channel, buffer, sizeof(buffer)); - if (rc > 0) { - got_data = 1; - while (result->stderr_len + rc >= stderr_capacity) { - stderr_capacity *= 2; - char *new_buf = TS_REALLOC_PSRAM(result->stderr_data, stderr_capacity); - if (!new_buf) { - set_error(session, "Out of memory"); - ts_ssh_exec_result_free(result); - libssh2_channel_free(channel); - return ESP_ERR_NO_MEM; + if (*len + rc + 1 > capacity[stream]) { + size_t next = capacity[stream] ? capacity[stream] * 2 : 1024; + if (next > limit + 1) + next = limit + 1; + char *grown = TS_REALLOC_PSRAM(*data, next); + if (!grown) { + ret = ESP_ERR_NO_MEM; + goto failed; + } + *data = grown; + capacity[stream] = next; } - result->stderr_data = new_buf; + memcpy(*data + *len, buffer, rc); + *len += rc; + (*data)[*len] = 0; } - memcpy(result->stderr_data + result->stderr_len, buffer, rc); - result->stderr_len += rc; - } else if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { - set_error(session, "Channel stderr read error: %d", rc); - ts_ssh_exec_result_free(result); - libssh2_channel_free(channel); - return ESP_FAIL; } - } while (rc > 0); - - /* 用 channel EOF 判断是否结束(不再依赖 rc 的值) */ - if (libssh2_channel_eof(channel)) { - break; } - - /* 收到数据则重置等待计数;无数据则累计,超过 300 轮(~5 分钟)视为超时 */ - if (got_data) { - wait_rounds = 0; - } else { - wait_rounds++; - if (wait_rounds > 300) { - set_error(session, "Read timeout: no EOF after %d wait rounds", wait_rounds); - break; /* 不返回错误,保留已读数据 */ - } - } - - /* 未 EOF:等待更多数据到达后再循环 */ - wait_socket(session->sock, session->session, 1000); - } - - /* 添加字符串终止符 */ - result->stdout_data[result->stdout_len] = '\0'; - result->stderr_data[result->stderr_len] = '\0'; - - /* 关闭通道并获取退出码 */ - while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 1000); - } - - if (rc == 0) { - result->exit_code = libssh2_channel_get_exit_status(channel); - } - + /* Drain buffered bytes even when EOF arrived with the last packet. */ + if (!got_data && libssh2_channel_eof(channel)) + break; + if (!got_data && wait_socket(s) < 0) + goto timeout; + } + while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) + if (wait_socket(s) < 0) + goto timeout; + if (rc) + goto failed; + int status = libssh2_channel_get_exit_status(channel); + if (exit_code) + *exit_code = status; + if (result) + result->exit_code = status; libssh2_channel_free(channel); - - ESP_LOGD(TAG, "Command completed: exit_code=%d, stdout_len=%zu, stderr_len=%zu", - result->exit_code, result->stdout_len, result->stderr_len); return ESP_OK; +timeout: + ret = ESP_ERR_TIMEOUT; +failed: + /* A timed-out command has an unknown remote outcome. Dispose the transport + * and all its channels once; never return partial output as success. */ + ts_ssh_disconnect(s); + if (result) + ts_ssh_exec_result_free(result); + return ret; } -esp_err_t ts_ssh_exec_stream(ts_ssh_session_t session, const char *command, - ts_ssh_output_cb_t callback, void *user_data, - int *exit_code) -{ - if (!session || !command || !callback) { - return ESP_ERR_INVALID_ARG; - } - - if (session->state != TS_SSH_STATE_CONNECTED) { - set_error(session, "Not connected"); - return ESP_ERR_INVALID_STATE; - } - - /* 清除中止标志 */ - session->abort_flag = false; - - /* 打开通道 */ - LIBSSH2_CHANNEL *channel = NULL; - int rc; - - while ((channel = libssh2_channel_open_session(session->session)) == NULL && - libssh2_session_last_error(session->session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) { - if (session->abort_flag) { - set_error(session, "Aborted by user"); - return ESP_ERR_TIMEOUT; - } - wait_socket(session->sock, session->session, 1000); - } - - if (!channel) { - char *err_msg = NULL; - libssh2_session_last_error(session->session, &err_msg, NULL, 0); - set_error(session, "Failed to open channel: %s", err_msg ? err_msg : "unknown"); - return ESP_FAIL; - } - - /* 执行命令 */ - while ((rc = libssh2_channel_exec(channel, command)) == LIBSSH2_ERROR_EAGAIN) { - if (session->abort_flag) { - libssh2_channel_free(channel); - set_error(session, "Aborted by user"); - return ESP_ERR_TIMEOUT; - } - wait_socket(session->sock, session->session, 1000); - } - - if (rc != 0) { - set_error(session, "Failed to exec command: rc=%d", rc); - libssh2_channel_free(channel); - return ESP_FAIL; - } - - /* 流式读取输出 */ - char buffer[512]; - bool aborted = false; - for (;;) { - /* 检查中止标志 */ - if (session->abort_flag) { - aborted = true; - break; - } - - /* 读取 stdout */ - do { - rc = libssh2_channel_read(channel, buffer, sizeof(buffer)); - if (rc > 0) { - callback(buffer, rc, false, user_data); - } - if (session->abort_flag) { - aborted = true; - break; - } - } while (rc > 0); - - if (aborted) break; - - /* 读取 stderr */ - do { - rc = libssh2_channel_read_stderr(channel, buffer, sizeof(buffer)); - if (rc > 0) { - callback(buffer, rc, true, user_data); - } - if (session->abort_flag) { - aborted = true; - break; - } - } while (rc > 0); - - if (aborted) break; - - /* 检查 channel 是否已经结束(远程命令退出)*/ - if (libssh2_channel_eof(channel)) { - break; /* 命令已完成,退出循环 */ - } - - if (rc == LIBSSH2_ERROR_EAGAIN) { - wait_socket(session->sock, session->session, 100); /* 减少等待时间以便更快响应中断 */ - } else if (rc == 0) { - /* 没有数据但 channel 未结束,短暂等待后继续 */ - wait_socket(session->sock, session->session, 50); - } else { - break; - } - } - - /* 关闭通道 */ - while ((rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN) { - if (session->abort_flag) break; /* 中止时也要快速退出 */ - wait_socket(session->sock, session->session, 100); - } - - if (exit_code) { - *exit_code = aborted ? -1 : ((rc == 0) ? libssh2_channel_get_exit_status(channel) : -1); - } +esp_err_t ts_ssh_exec(ts_ssh_session_t s, const char *command, ts_ssh_exec_result_t *result) { + return exec_command(s, command, NULL, NULL, result, NULL); +} - libssh2_channel_free(channel); - - if (aborted) { - set_error(session, "Aborted by user"); - return ESP_ERR_TIMEOUT; - } - return ESP_OK; +esp_err_t ts_ssh_exec_stream(ts_ssh_session_t s, const char *command, ts_ssh_output_cb_t callback, + void *context, int *exit_code) { + return exec_command(s, command, callback, context, NULL, exit_code); } -void ts_ssh_abort(ts_ssh_session_t session) -{ +void ts_ssh_abort(ts_ssh_session_t session) { if (session) { session->abort_flag = true; } } -void ts_ssh_exec_result_free(ts_ssh_exec_result_t *result) -{ +void ts_ssh_exec_result_free(ts_ssh_exec_result_t *result) { if (result) { free(result->stdout_data); free(result->stderr_data); @@ -865,14 +499,12 @@ void ts_ssh_exec_result_free(ts_ssh_exec_result_t *result) } } -const char *ts_ssh_get_error(ts_ssh_session_t session) -{ +const char *ts_ssh_get_error(ts_ssh_session_t session) { return session ? session->error_msg : "Invalid session"; } esp_err_t ts_ssh_exec_simple(const ts_ssh_config_t *config, const char *command, - ts_ssh_exec_result_t *result) -{ + ts_ssh_exec_result_t *result) { ts_ssh_session_t session = NULL; esp_err_t ret; @@ -888,10 +520,10 @@ esp_err_t ts_ssh_exec_simple(const ts_ssh_config_t *config, const char *command, } ret = ts_ssh_exec(session, command, result); - + ts_ssh_disconnect(session); ts_ssh_session_destroy(session); - + return ret; } @@ -902,31 +534,23 @@ esp_err_t ts_ssh_exec_simple(const ts_ssh_config_t *config, const char *command, /** * @brief 获取内部 libssh2 会话句柄 */ -LIBSSH2_SESSION *ts_ssh_get_libssh2_session(ts_ssh_session_t session) -{ +LIBSSH2_SESSION *ts_ssh_get_libssh2_session(ts_ssh_session_t session) { return session ? session->session : NULL; } /** * @brief 获取 socket 文件描述符 */ -int ts_ssh_get_socket(ts_ssh_session_t session) -{ - return session ? session->sock : -1; -} +int ts_ssh_get_socket(ts_ssh_session_t session) { return session ? session->sock : -1; } /** * @brief 获取远程主机地址 */ -const char *ts_ssh_get_host(ts_ssh_session_t session) -{ +const char *ts_ssh_get_host(ts_ssh_session_t session) { return session ? session->host_copy : NULL; } /** * @brief 获取远程端口 */ -uint16_t ts_ssh_get_port(ts_ssh_session_t session) -{ - return session ? session->config.port : 0; -} \ No newline at end of file +uint16_t ts_ssh_get_port(ts_ssh_session_t session) { return session ? session->config.port : 0; } \ No newline at end of file diff --git a/components/ts_security/src/ts_ssh_commands_config.c b/components/ts_security/src/ts_ssh_commands_config.c index c9d9e5f..60f530c 100644 --- a/components/ts_security/src/ts_ssh_commands_config.c +++ b/components/ts_security/src/ts_ssh_commands_config.c @@ -1,3 +1,4 @@ +#include "ts_ssh_service.h" /** * @file ts_ssh_commands_config.c * @brief SSH Command Configuration Storage Implementation @@ -219,6 +220,7 @@ static bool s_pending_export = false; /** 正在从 SD 卡加载中(禁止触发同步) */ static bool s_loading_from_sdcard = false; +static TaskHandle_t initial_loader; /** * @brief 延迟加载/导出任务 - 在独立任务中处理 SD 卡操作(避免 main 任务栈溢出) @@ -228,9 +230,11 @@ static bool s_loading_from_sdcard = false; static void deferred_export_task(void *arg) { (void)arg; + initial_loader = xTaskGetCurrentTaskHandle(); vTaskDelay(pdMS_TO_TICKS(2000)); /* 等待系统稳定、SD 卡挂载完成 */ if (!s_state.initialized) { + initial_loader = NULL; vTaskDelete(NULL); return; } @@ -265,8 +269,14 @@ static void deferred_export_task(void *arg) if (sdcard_has_config) { /* SD 卡有配置,清空 NVS 后导入(SD 卡为权威来源) */ ESP_LOGI(TAG, "SD card has config, clearing NVS and importing..."); - ts_ssh_commands_config_clear(); - + esp_err_t cleared = ts_ssh_commands_config_clear(); + if (cleared != ESP_OK) { + s_loading_from_sdcard = false; + initial_loader = NULL; + vTaskDelete(NULL); + return; + } + esp_err_t import_ret = ts_ssh_commands_config_import_from_sdcard(false); size_t count = ts_ssh_commands_config_count(); @@ -286,6 +296,7 @@ static void deferred_export_task(void *arg) } s_pending_export = false; + initial_loader = NULL; vTaskDelete(NULL); } @@ -356,9 +367,8 @@ bool ts_ssh_commands_config_is_initialized(void) /* CRUD Operations */ /*===========================================================================*/ -esp_err_t ts_ssh_commands_config_add(const ts_ssh_command_config_t *config, - char *out_id, size_t out_id_size) -{ +static esp_err_t command_add_impl(const ts_ssh_command_config_t *config, char *out_id, + size_t out_id_size) { /* 强制要求 ID:前端必须提供格式正确的语义化 ID */ if (!s_state.initialized || !config || !config->id[0] || !config->host_id[0] || !config->name[0]) { @@ -466,8 +476,7 @@ esp_err_t ts_ssh_commands_config_add(const ts_ssh_command_config_t *config, return ret; } -esp_err_t ts_ssh_commands_config_remove(const char *id) -{ +static esp_err_t command_remove_impl(const char *id) { if (!s_state.initialized || !id || !id[0]) { return ESP_ERR_INVALID_ARG; } @@ -486,7 +495,7 @@ esp_err_t ts_ssh_commands_config_remove(const char *id) if (strcmp(entry.id, id) == 0) { ret = nvs_erase_key(s_state.nvs, key); if (ret == ESP_OK) { - nvs_commit(s_state.nvs); + ret = nvs_commit(s_state.nvs); ESP_LOGI(TAG, "Removed SSH command: %s (%s)", entry.name, id); } break; @@ -685,8 +694,7 @@ size_t ts_ssh_commands_config_count(void) return count; } -esp_err_t ts_ssh_commands_config_clear(void) -{ +static esp_err_t command_clear_impl(void) { if (!s_state.initialized) { return ESP_ERR_INVALID_STATE; } @@ -1379,7 +1387,11 @@ esp_err_t ts_ssh_commands_config_import_from_sdcard(bool merge) /* 如果不是合并模式,先清空现有配置 */ if (!merge) { - ts_ssh_commands_config_clear(); + esp_err_t cleared = ts_ssh_commands_config_clear(); + if (cleared != ESP_OK) { + s_loading_from_sdcard = false; + return cleared; + } } /* 只从目录加载独立文件(.tscfg 优先于 .json) */ @@ -1413,3 +1425,50 @@ void ts_ssh_commands_config_sync_to_sdcard(void) * 必须使用 DRAM 栈,因为内部会访问 NVS */ xTaskCreate(async_sync_task, "ssh_cmd_sync", 8192, NULL, 2, NULL); } + +esp_err_t ts_ssh_commands_config_add(const ts_ssh_command_config_t *cfg, char *out, size_t size) { + if (!cfg) + return ESP_ERR_INVALID_ARG; + ts_ssh_binding_lock(); + ts_ssh_command_config_t *old = + heap_caps_malloc(sizeof(*old), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!old) { + ts_ssh_binding_unlock(); + return ESP_ERR_NO_MEM; + } + esp_err_t got = ts_ssh_commands_config_get(cfg->id, old); + bool changed = got == ESP_OK && + (strcmp(old->host_id, cfg->host_id) || strcmp(old->name, cfg->name) || + strcmp(old->command, cfg->command) || strcmp(old->var_name, cfg->var_name) || + old->nohup != cfg->nohup || old->service_mode != cfg->service_mode); + bool busy = (changed || got == ESP_ERR_NOT_FOUND) && ts_ssh_service_command_protected(cfg->id); + free(old); + esp_err_t ret = busy ? ESP_ERR_INVALID_STATE : command_add_impl(cfg, out, size); + ts_ssh_binding_unlock(); + return ret; +} +esp_err_t ts_ssh_commands_config_remove(const char *id) { + if (!id) + return ESP_ERR_INVALID_ARG; + ts_ssh_binding_lock(); + uint32_t credential = 0; + esp_err_t ret = ts_ssh_service_command_protected(id) ? ESP_ERR_INVALID_STATE + : ts_ssh_service_delete_begin(id, &credential); + if (ret == ESP_OK) { + ret = command_remove_impl(id); + ts_ssh_service_delete_finish(id, credential, ret == ESP_OK); + } + ts_ssh_binding_unlock(); + return ret; +} +esp_err_t ts_ssh_commands_config_clear(void) { + ts_ssh_binding_lock(); + esp_err_t ret = + (xTaskGetCurrentTaskHandle() == initial_loader ? ts_ssh_service_any_in_use() + : ts_ssh_service_host_protected(NULL)) + ? ESP_ERR_INVALID_STATE + : command_clear_impl(); + if (ret == ESP_OK) ts_ssh_service_forget_stopped(); + ts_ssh_binding_unlock(); + return ret; +} diff --git a/components/ts_security/src/ts_ssh_hosts_config.c b/components/ts_security/src/ts_ssh_hosts_config.c index 346c09b..40b399f 100644 --- a/components/ts_security/src/ts_ssh_hosts_config.c +++ b/components/ts_security/src/ts_ssh_hosts_config.c @@ -1,3 +1,4 @@ +#include "ts_ssh_service.h" /** * @file ts_ssh_hosts_config.c * @brief SSH Host Configuration Storage Implementation @@ -85,6 +86,7 @@ static bool s_hosts_pending_export = false; /** 正在从 SD 卡加载中(禁止触发同步) */ static bool s_loading_from_sdcard = false; +static TaskHandle_t initial_loader; /** * @brief 延迟加载/导出任务 - 在独立任务中处理 SD 卡操作(避免 main 任务栈溢出) @@ -94,9 +96,11 @@ static bool s_loading_from_sdcard = false; static void hosts_deferred_export_task(void *arg) { (void)arg; + initial_loader = xTaskGetCurrentTaskHandle(); vTaskDelay(pdMS_TO_TICKS(2500)); /* 等待系统稳定,错开 commands 加载 */ if (!s_state.initialized) { + initial_loader = NULL; vTaskDelete(NULL); return; } @@ -131,8 +135,14 @@ static void hosts_deferred_export_task(void *arg) if (sdcard_has_config) { /* SD 卡有配置,清空 NVS 后导入(SD 卡为权威来源) */ ESP_LOGI(TAG, "SD card has config, clearing NVS and importing..."); - ts_ssh_hosts_config_clear(); - + esp_err_t cleared = ts_ssh_hosts_config_clear(); + if (cleared != ESP_OK) { + s_loading_from_sdcard = false; + initial_loader = NULL; + vTaskDelete(NULL); + return; + } + esp_err_t import_ret = ts_ssh_hosts_config_import_from_sdcard(false); size_t count = ts_ssh_hosts_config_count(); @@ -152,6 +162,7 @@ static void hosts_deferred_export_task(void *arg) } s_hosts_pending_export = false; + initial_loader = NULL; vTaskDelete(NULL); } @@ -217,8 +228,7 @@ bool ts_ssh_hosts_config_is_initialized(void) /* CRUD Operations */ /*===========================================================================*/ -esp_err_t ts_ssh_hosts_config_add(const ts_ssh_host_config_t *config) -{ +static esp_err_t host_add_impl(const ts_ssh_host_config_t *config) { if (!s_state.initialized || !config || !config->id[0] || !config->host[0]) { return ESP_ERR_INVALID_ARG; } @@ -289,8 +299,7 @@ esp_err_t ts_ssh_hosts_config_add(const ts_ssh_host_config_t *config) return ret; } -esp_err_t ts_ssh_hosts_config_remove(const char *id) -{ +static esp_err_t host_remove_impl(const char *id) { if (!s_state.initialized || !id || !id[0]) { return ESP_ERR_INVALID_ARG; } @@ -505,8 +514,7 @@ esp_err_t ts_ssh_hosts_config_touch(const char *id) return ret; } -esp_err_t ts_ssh_hosts_config_clear(void) -{ +static esp_err_t host_clear_impl(void) { if (!s_state.initialized) { return ESP_ERR_INVALID_STATE; } @@ -1046,7 +1054,11 @@ esp_err_t ts_ssh_hosts_config_import_from_sdcard(bool merge) /* 如果不是合并模式,先清空现有配置 */ if (!merge) { - ts_ssh_hosts_config_clear(); + esp_err_t cleared = ts_ssh_hosts_config_clear(); + if (cleared != ESP_OK) { + s_loading_from_sdcard = false; + return cleared; + } } /* 只从目录加载独立文件(.tscfg 优先于 .json) */ @@ -1080,3 +1092,38 @@ void ts_ssh_hosts_config_sync_to_sdcard(void) * 必须使用 DRAM 栈,因为内部会访问 NVS */ xTaskCreate(hosts_async_sync_task, "ssh_host_sync", 8192, NULL, 2, NULL); } + +esp_err_t ts_ssh_hosts_config_add(const ts_ssh_host_config_t *cfg) { + if (!cfg) + return ESP_ERR_INVALID_ARG; + ts_ssh_binding_lock(); + ts_ssh_host_config_t old; + esp_err_t got = ts_ssh_hosts_config_get(cfg->id, &old); + bool changed = + got == ESP_OK && (strcmp(old.host, cfg->host) || old.port != cfg->port || + strcmp(old.username, cfg->username) || strcmp(old.keyid, cfg->keyid) || + old.auth_type != cfg->auth_type); + esp_err_t ret = (changed || got == ESP_ERR_NOT_FOUND) && ts_ssh_service_host_protected(cfg->id) ? ESP_ERR_INVALID_STATE + : host_add_impl(cfg); + ts_ssh_binding_unlock(); + return ret; +} +esp_err_t ts_ssh_hosts_config_remove(const char *id) { + if (!id) + return ESP_ERR_INVALID_ARG; + ts_ssh_binding_lock(); + esp_err_t ret = + ts_ssh_service_host_protected(id) ? ESP_ERR_INVALID_STATE : host_remove_impl(id); + ts_ssh_binding_unlock(); + return ret; +} +esp_err_t ts_ssh_hosts_config_clear(void) { + ts_ssh_binding_lock(); + esp_err_t ret = + (xTaskGetCurrentTaskHandle() == initial_loader ? ts_ssh_service_any_in_use() + : ts_ssh_service_host_protected(NULL)) + ? ESP_ERR_INVALID_STATE + : host_clear_impl(); + ts_ssh_binding_unlock(); + return ret; +} diff --git a/components/ts_security/src/ts_ssh_log_watch.c b/components/ts_security/src/ts_ssh_log_watch.c index 4718822..635010f 100644 --- a/components/ts_security/src/ts_ssh_log_watch.c +++ b/components/ts_security/src/ts_ssh_log_watch.c @@ -1,548 +1,301 @@ -/** - * @file ts_ssh_log_watch.c - * @brief SSH Service Log Watcher Implementation - * - * Uses a dedicated task with large stack (8KB) for SSH operations - * instead of running in esp_timer callback to avoid stack overflow. - */ - #include "ts_ssh_log_watch.h" -#include "ts_ssh_client.h" -#include "ts_ssh_hosts_config.h" -#include "ts_keystore.h" -#include "ts_variable.h" +#include "esp_heap_caps.h" #include "esp_log.h" #include "esp_timer.h" #include "freertos/FreeRTOS.h" -#include "freertos/task.h" #include "freertos/semphr.h" -#include "freertos/queue.h" -#include "esp_heap_caps.h" +#include "freertos/task.h" +#include "ts_keystore.h" +#include "ts_ssh_client.h" +#include "ts_ssh_hosts_config.h" +#include "ts_ssh_probe.h" +#include "ts_ssh_service.h" +#include "ts_variable.h" +#include +#include +#include #include -#include - -static const char *TAG = "ssh_log_watch"; -/* Task stack size - SSH operations need large stack */ -#define LOG_WATCH_TASK_STACK_SIZE (8 * 1024) -#define LOG_WATCH_TASK_PRIORITY 5 +#ifndef CONFIG_TS_SSH_LOG_WATCH_MAX +#define CONFIG_TS_SSH_LOG_WATCH_MAX 32 +#endif +#define LOG_WATCH_TASK_STACK_SIZE (8 * 1024) +#define LOG_WATCH_TASK_PRIORITY 5 -/*===========================================================================*/ -/* Internal Types */ -/*===========================================================================*/ - -typedef struct ts_ssh_log_watch_task { - ts_ssh_log_watch_config_t config; - uint32_t start_time; - bool is_running; - bool stop_requested; - TaskHandle_t task_handle; - struct ts_ssh_log_watch_task *next; -} ts_ssh_log_watch_task_t; - -/*===========================================================================*/ -/* Static Variables */ -/*===========================================================================*/ - -static ts_ssh_log_watch_task_t *s_task_list = NULL; -static SemaphoreHandle_t s_mutex = NULL; - -/*===========================================================================*/ -/* Helper Functions */ -/*===========================================================================*/ +typedef struct { + ts_ssh_log_watch_config_t *config; + TaskHandle_t task; + uint32_t generation; + atomic_bool cancel; + int64_t deadline; +} watch_slot_t; +static watch_slot_t slots[CONFIG_TS_SSH_LOG_WATCH_MAX]; +static SemaphoreHandle_t mutex; +static const char *TAG = "ssh_log_watch"; -/** - * @brief 初始化互斥锁 - */ -static void ensure_mutex_init(void) { - if (!s_mutex) { - s_mutex = xSemaphoreCreateMutex(); - } +/* Initialized by the security service before API/rule execution starts. */ +esp_err_t ts_ssh_log_watch_init(void) { + if (!mutex) + mutex = xSemaphoreCreateMutex(); + return mutex ? ESP_OK : ESP_ERR_NO_MEM; } -/** - * @brief 更新变量状态 - */ -static void update_status_var(const char *var_name, const char *status) { - char full_name[64]; - snprintf(full_name, sizeof(full_name), "%s.status", var_name); - - esp_err_t ret = ts_variable_set_string(full_name, status); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to set variable %s: %s", full_name, esp_err_to_name(ret)); - } else { - ESP_LOGI(TAG, "Variable %s = %s", full_name, status); - } +static bool cancelled(void *context) { + watch_slot_t *slot = context; + return atomic_load(&slot->cancel) || esp_timer_get_time() >= slot->deadline; } -/** - * @brief 更新就绪时间 - */ -static void update_ready_time(const char *var_name) { - char full_name[64]; - snprintf(full_name, sizeof(full_name), "%s.ready_time", var_name); - - time_t now = time(NULL); - ts_variable_set_int(full_name, (int32_t)now); +static void publish(watch_slot_t *slot, const char *status) { + const ts_ssh_log_watch_config_t *cfg = slot->config; + /* Generation/state is checked atomically with publication by service registry. + * Cancellation alone never declares the remote process stopped. */ + if (!atomic_load(&slot->cancel)) + ts_ssh_service_observe(cfg->command_id, cfg->run_generation, status, cfg->var_name); } -/** - * @brief 执行 SSH 命令读取日志(改用 grep 在远程搜索模式) - * @param host_id 主机 ID - * @param log_file 日志文件路径 - * @param ready_pattern 就绪模式(为空则跳过检查) - * @param fail_pattern 失败模式(为空则跳过检查) - * @param result 输出:0=未找到, 1=找到ready, -1=找到fail, -2=文件不存在 - */ -static esp_err_t check_log_pattern_via_ssh(const char *host_id, const char *log_file, - const char *ready_pattern, const char *fail_pattern, - int *result) { - ESP_LOGI(TAG, "Checking log: host_id='%s', log_file='%s'", host_id, log_file); - *result = 0; - - // 获取主机配置 - ts_ssh_host_config_t host_cfg; - esp_err_t ret = ts_ssh_hosts_config_get(host_id, &host_cfg); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Host '%s' not found: %s", host_id, esp_err_to_name(ret)); - return ret; - } - - // 加载私钥 - char *key_data = NULL; +static esp_err_t check_log(watch_slot_t *slot, const char *command, int *match) { + ts_ssh_host_config_t host; + ts_ssh_session_t session = NULL; + ts_ssh_exec_result_t result = {0}; + char *key = NULL; size_t key_len = 0; - if (host_cfg.keyid[0]) { - ret = ts_keystore_load_private_key(host_cfg.keyid, &key_data, &key_len); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to load key '%s': %s", host_cfg.keyid, esp_err_to_name(ret)); - return ret; - } - } else { - ESP_LOGE(TAG, "Host %s has no key configured", host_id); - return ESP_ERR_INVALID_STATE; - } - - // 构建检查命令:先检查文件是否存在,再用 grep 搜索模式 - // grep -q 静默模式,找到返回 0,未找到返回 1 - // 输出格式: "EXISTS:READY:FAIL" (1/0 表示是否匹配) - char cmd[1024]; - - // 转义 pattern 中的单引号(简单替换为 '\'') - char escaped_ready[256] = {0}; - char escaped_fail[256] = {0}; - - // 简单复制,实际使用时 pattern 不应包含单引号 - if (ready_pattern && ready_pattern[0]) { - strncpy(escaped_ready, ready_pattern, sizeof(escaped_ready) - 1); + esp_err_t ret = ts_ssh_hosts_config_get(slot->config->host_id, &host); + if (ret != ESP_OK) + goto done; + if (!host.keyid[0]) { + ret = ESP_ERR_INVALID_STATE; + goto done; } - if (fail_pattern && fail_pattern[0]) { - strncpy(escaped_fail, fail_pattern, sizeof(escaped_fail) - 1); + ret = ts_keystore_load_private_key(host.keyid, &key, &key_len); + if (ret != ESP_OK) + goto done; + ts_ssh_config_t cfg = TS_SSH_DEFAULT_CONFIG(); + cfg.host = host.host; + cfg.port = host.port; + cfg.username = host.username; + cfg.auth_method = TS_SSH_AUTH_PUBLICKEY; + cfg.auth.key.private_key = (const uint8_t *)key; + cfg.auth.key.private_key_len = key_len; + cfg.timeout_ms = 5000; + cfg.cancelled = cancelled; + cfg.cancel_context = slot; + cfg.max_output_bytes = 128; + ret = ts_ssh_session_create(&cfg, &session); + if (ret == ESP_OK) + ret = ts_ssh_connect(session); + if (ret == ESP_OK) + ret = ts_ssh_service_verify_instance(slot->config->command_id, slot->config->run_generation, session); + if (ret == ESP_OK) + ret = ts_ssh_exec(session, command, &result); + if (ret == ESP_OK) + ret = ts_ssh_service_verify_instance(slot->config->command_id, slot->config->run_generation, session); + if (ret == ESP_OK) { + if (result.exit_code != 0) + ret = ESP_FAIL; + else if (ts_ssh_probe_token(result.stdout_data, "FAIL")) + *match = -1; + else if (ts_ssh_probe_token(result.stdout_data, "READY")) + *match = 1; + else if (ts_ssh_probe_token(result.stdout_data, "WAITING") || + ts_ssh_probe_token(result.stdout_data, "NOTFOUND")) + *match = 0; + else + ret = ESP_ERR_INVALID_RESPONSE; } - - // 构建命令:检查文件存在、grep ready pattern、grep fail pattern - // 使用 grep -F 进行固定字符串匹配(不解释正则) - if (escaped_fail[0] && escaped_ready[0]) { - snprintf(cmd, sizeof(cmd), - "if [ ! -f '%s' ]; then echo 'NOTFOUND'; " - "elif grep -qF '%s' '%s' 2>/dev/null; then echo 'FAIL'; " - "elif grep -qF '%s' '%s' 2>/dev/null; then echo 'READY'; " - "else echo 'WAITING'; fi", - log_file, escaped_fail, log_file, escaped_ready, log_file); - } else if (escaped_ready[0]) { - snprintf(cmd, sizeof(cmd), - "if [ ! -f '%s' ]; then echo 'NOTFOUND'; " - "elif grep -qF '%s' '%s' 2>/dev/null; then echo 'READY'; " - "else echo 'WAITING'; fi", - log_file, escaped_ready, log_file); - } else { - // 没有 pattern,只检查文件是否存在 - snprintf(cmd, sizeof(cmd), - "[ -f '%s' ] && echo 'EXISTS' || echo 'NOTFOUND'", log_file); - } - - ESP_LOGD(TAG, "Check command: %s", cmd); - - // 配置 SSH 连接 - ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); - config.host = host_cfg.host; - config.port = host_cfg.port; - config.username = host_cfg.username; - config.timeout_ms = 5000; - config.auth_method = TS_SSH_AUTH_PUBLICKEY; - config.auth.key.private_key = (const uint8_t *)key_data; - config.auth.key.private_key_len = key_len; - - // 创建 SSH 会话 - ts_ssh_session_t session = NULL; - ret = ts_ssh_session_create(&config, &session); - if (ret != ESP_OK || !session) { - ESP_LOGE(TAG, "Failed to create SSH session: %s", esp_err_to_name(ret)); - free(key_data); - return ret != ESP_OK ? ret : ESP_ERR_NO_MEM; - } - - // 连接 - ret = ts_ssh_connect(session); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "SSH connect failed: %s", esp_err_to_name(ret)); +done: + ts_ssh_exec_result_free(&result); + if (session) ts_ssh_session_destroy(session); - free(key_data); - return ret; - } - - // 执行命令 - ts_ssh_exec_result_t exec_result = {0}; - ret = ts_ssh_exec(session, cmd, &exec_result); - - if (ret == ESP_OK && exec_result.stdout_data) { - // 解析输出结果 - const char *output = exec_result.stdout_data; - ESP_LOGI(TAG, "Check result: '%s'", output); - - if (strstr(output, "NOTFOUND")) { - *result = -2; // 文件不存在 - } else if (strstr(output, "FAIL")) { - *result = -1; // 找到失败模式 - } else if (strstr(output, "READY")) { - *result = 1; // 找到就绪模式 - } else { - *result = 0; // 等待中 - } - - free(exec_result.stdout_data); - if (exec_result.stderr_data) free(exec_result.stderr_data); - } else { - ESP_LOGW(TAG, "SSH exec failed: %s", esp_err_to_name(ret)); - } - - ts_ssh_disconnect(session); - ts_ssh_session_destroy(session); - free(key_data); - + free(key); return ret; } -/** - * @brief Log watch task - runs SSH operations in dedicated task with large stack - */ -static void log_watch_task(void *arg) { - ts_ssh_log_watch_task_t *task = (ts_ssh_log_watch_task_t *)arg; - - ESP_LOGI(TAG, "========================================"); - ESP_LOGI(TAG, "Log watch task started:"); - ESP_LOGI(TAG, " var_name: '%s'", task->config.var_name); - ESP_LOGI(TAG, " host_id: '%s'", task->config.host_id); - ESP_LOGI(TAG, " log_file: '%s'", task->config.log_file); - ESP_LOGI(TAG, " ready_pattern: '%s'", task->config.ready_pattern); - ESP_LOGI(TAG, " fail_pattern: '%s'", task->config.fail_pattern); - ESP_LOGI(TAG, " timeout: %u sec, interval: %u ms", task->config.timeout_sec, task->config.check_interval_ms); - ESP_LOGI(TAG, "========================================"); - - while (task->is_running && !task->stop_requested) { - // 检查超时 - uint32_t elapsed = (xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000 - task->start_time; - if (elapsed >= task->config.timeout_sec) { - ESP_LOGW(TAG, "Log watch timeout for %s after %u seconds", - task->config.var_name, elapsed); - update_status_var(task->config.var_name, "timeout"); - break; +static void worker(void *context) { + watch_slot_t *slot = context; + /* Creator registers the task handle and initial state before releasing gate. */ + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + char *command = NULL; + if (slot->config->recovery_only) { + while (!cancelled(slot)) { + if (!ts_ssh_service_recover(slot->config->command_id, slot->config->run_generation)) break; + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(slot->config->check_interval_ms)); } - - // 使用 grep 在远程检查模式 - int check_result = 0; - esp_err_t ret = check_log_pattern_via_ssh( - task->config.host_id, - task->config.log_file, - task->config.ready_pattern, - task->config.fail_pattern, - &check_result - ); - - if (ret == ESP_OK) { - switch (check_result) { - case 1: // READY - ESP_LOGI(TAG, "✅ Service ready: pattern '%s' found in log", - task->config.ready_pattern); - update_status_var(task->config.var_name, "ready"); - update_ready_time(task->config.var_name); - goto task_done; - - case -1: // FAIL - ESP_LOGE(TAG, "❌ Service failed: pattern '%s' found in log", - task->config.fail_pattern); - update_status_var(task->config.var_name, "failed"); - goto task_done; - - case -2: // NOTFOUND - ESP_LOGD(TAG, "Log file not found yet, waiting... (elapsed=%us)", elapsed); - break; - - default: // WAITING - ESP_LOGI(TAG, "Waiting for pattern '%s' (elapsed=%us/%us)", - task->config.ready_pattern, elapsed, task->config.timeout_sec); - break; - } - } else { - ESP_LOGW(TAG, "Check failed (will retry): %s", esp_err_to_name(ret)); - } - - // 等待下次检查 - vTaskDelay(pdMS_TO_TICKS(task->config.check_interval_ms)); + goto done; + } + command = heap_caps_malloc(3072, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!command || !ts_ssh_log_probe_command(slot->config->log_file, slot->config->ready_pattern, + slot->config->fail_pattern, command, 3072)) { + publish(slot, "unknown"); + goto done; } - -task_done: - task->is_running = false; - - ESP_LOGI(TAG, "Log watch task finished for %s", task->config.var_name); - - // 自动清理:从链表移除 - if (s_mutex) { - xSemaphoreTake(s_mutex, portMAX_DELAY); - ts_ssh_log_watch_task_t **pp = &s_task_list; - while (*pp) { - if (*pp == task) { - *pp = task->next; - break; - } - pp = &(*pp)->next; + while (!cancelled(slot)) { + int match = 0; + esp_err_t ret = check_log(slot, command, &match); + if (cancelled(slot)) + break; + if (ret == ESP_OK && match) { + publish(slot, match > 0 ? "ready" : "failed"); + goto done; + } + if (ret != ESP_OK) { + publish(slot, "unknown"); + if (ret == TS_SSH_ERR_HOST_UNKNOWN || ret == TS_SSH_ERR_HOST_CHANGED || + ret == ESP_ERR_INVALID_STATE) + goto done; } - xSemaphoreGive(s_mutex); + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(slot->config->check_interval_ms)); } - - free(task); - vTaskDelete(NULL); + if (!atomic_load(&slot->cancel)) + publish(slot, "timeout"); +done: + free(command); + xSemaphoreTake(mutex, portMAX_DELAY); + ts_ssh_log_watch_config_t *cfg = slot->config; + slot->config = NULL; + slot->task = NULL; + xSemaphoreGive(mutex); + if (cfg->recovery_only) + ts_ssh_service_recovery_done(cfg->command_id, cfg->run_generation); + else + ts_ssh_service_recovery_kick(cfg->command_id); + free(cfg); + vTaskDelete(NULL); /* Only the resource-owning task deletes itself. */ } -/*===========================================================================*/ -/* Public API */ -/*===========================================================================*/ - -esp_err_t ts_ssh_log_watch_start(const ts_ssh_log_watch_config_t *config, - ts_ssh_log_watch_handle_t *out_handle) { - if (!config || !config->host_id[0] || !config->log_file[0] || - !config->ready_pattern[0] || !config->var_name[0]) { +esp_err_t ts_ssh_log_watch_start(const ts_ssh_log_watch_config_t *cfg, + ts_ssh_log_watch_handle_t *out) { + if (out) + *out = 0; + if (!mutex) + return ESP_ERR_INVALID_STATE; + if (!cfg || !cfg->host_id[0] || (!cfg->recovery_only && (!cfg->log_file[0] || !cfg->ready_pattern[0])) || + !cfg->var_name[0] || !cfg->command_id[0] || !cfg->run_generation || !cfg->timeout_sec || + !cfg->check_interval_ms) return ESP_ERR_INVALID_ARG; - } - - ensure_mutex_init(); - - // 检查是否已有同名变量的监控任务运行中 - xSemaphoreTake(s_mutex, portMAX_DELAY); - ts_ssh_log_watch_task_t *existing = s_task_list; - while (existing) { - if (strcmp(existing->config.var_name, config->var_name) == 0 && existing->is_running) { - xSemaphoreGive(s_mutex); - ESP_LOGW(TAG, "Log watch for '%s' already running, stopping old one first", config->var_name); - // 停止旧任务 - existing->stop_requested = true; - // 等待旧任务结束(最多等 2 秒) - for (int i = 0; i < 20 && existing->is_running; i++) { - vTaskDelay(pdMS_TO_TICKS(100)); - } - xSemaphoreTake(s_mutex, portMAX_DELAY); - break; + if (!ts_ssh_service_observation_valid(cfg->command_id, cfg->run_generation)) + return ESP_ERR_INVALID_STATE; + ts_ssh_log_watch_config_t *copy = + heap_caps_malloc(sizeof(*copy), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!copy) + return ESP_ERR_NO_MEM; + *copy = *cfg; + xSemaphoreTake(mutex, portMAX_DELAY); + int index = -1; + for (int i = 0; i < CONFIG_TS_SSH_LOG_WATCH_MAX; i++) { + if (slots[i].config && (!strcmp(slots[i].config->var_name, cfg->var_name) || + !strcmp(slots[i].config->command_id, cfg->command_id))) { + xSemaphoreGive(mutex); + free(copy); + return ESP_ERR_INVALID_STATE; } - existing = existing->next; + if (!slots[i].config && slots[i].generation < 0xffffff && index < 0) + index = i; } - xSemaphoreGive(s_mutex); - - // 分配任务结构(使用 PSRAM) - ts_ssh_log_watch_task_t *task = heap_caps_calloc(1, sizeof(ts_ssh_log_watch_task_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!task) { - task = calloc(1, sizeof(ts_ssh_log_watch_task_t)); // Fallback to DRAM - if (!task) { - ESP_LOGE(TAG, "Failed to allocate task"); - return ESP_ERR_NO_MEM; - } + if (index < 0) { + xSemaphoreGive(mutex); + free(copy); + return ESP_ERR_NO_MEM; } - - // 复制配置 - memcpy(&task->config, config, sizeof(ts_ssh_log_watch_config_t)); - task->start_time = (xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000; - task->is_running = true; - task->stop_requested = false; - - // 设置初始状态 - update_status_var(config->var_name, "checking"); - - // 创建专用任务(使用较大的栈) - // 任务名包含变量名前缀以便调试识别 - char task_name[16]; - snprintf(task_name, sizeof(task_name), "lw_%.11s", config->var_name); - - BaseType_t ret = xTaskCreatePinnedToCore( - log_watch_task, - task_name, - LOG_WATCH_TASK_STACK_SIZE, - task, - LOG_WATCH_TASK_PRIORITY, - &task->task_handle, - 1 // Pin to core 1 to avoid blocking core 0 - ); - + watch_slot_t *slot = &slots[index]; + slot->config = copy; + ++slot->generation; + atomic_store(&slot->cancel, false); + slot->deadline = esp_timer_get_time() + (int64_t)cfg->timeout_sec * 1000000; + BaseType_t ret = xTaskCreatePinnedToCore(worker, "ssh_log_watch", LOG_WATCH_TASK_STACK_SIZE, + slot, LOG_WATCH_TASK_PRIORITY, &slot->task, 1); if (ret != pdPASS) { - ESP_LOGE(TAG, "Failed to create log watch task"); - free(task); + slot->config = NULL; + slot->task = NULL; + xSemaphoreGive(mutex); + free(copy); return ESP_ERR_NO_MEM; } - - // 加入任务链表 - xSemaphoreTake(s_mutex, portMAX_DELAY); - task->next = s_task_list; - s_task_list = task; - xSemaphoreGive(s_mutex); - - ESP_LOGI(TAG, "Started log watch: var=%s, pattern='%s', timeout=%us, interval=%ums", - config->var_name, config->ready_pattern, - config->timeout_sec, config->check_interval_ms); - - if (out_handle) { - *out_handle = task; - } - + if (out) + *out = (slot->generation << 8) | (index + 1); + /* Publication before gate; worker never uses a partly registered slot. */ + if (!cfg->recovery_only) publish(slot, "checking"); + xTaskNotifyGive(slot->task); + xSemaphoreGive(mutex); return ESP_OK; } +static watch_slot_t *find_handle(ts_ssh_log_watch_handle_t handle) { + unsigned index = (handle & 255); + if (!index || index > CONFIG_TS_SSH_LOG_WATCH_MAX) + return NULL; + watch_slot_t *slot = &slots[index - 1]; + return slot->config && slot->generation == (handle >> 8) ? slot : NULL; +} esp_err_t ts_ssh_log_watch_stop(ts_ssh_log_watch_handle_t handle) { - if (!handle) { - return ESP_ERR_INVALID_ARG; - } - - ts_ssh_log_watch_task_t *task = (ts_ssh_log_watch_task_t *)handle; - - // 请求任务停止 - task->stop_requested = true; - - // 等待任务自行退出(最多等待 2 秒) - int wait_count = 0; - while (task->is_running && wait_count < 20) { - vTaskDelay(pdMS_TO_TICKS(100)); - wait_count++; - } - - // 如果任务还在运行,强制删除 - if (task->is_running && task->task_handle) { - ESP_LOGW(TAG, "Force deleting log watch task"); - vTaskDelete(task->task_handle); - - // 从链表移除 - xSemaphoreTake(s_mutex, portMAX_DELAY); - ts_ssh_log_watch_task_t **pp = &s_task_list; - while (*pp) { - if (*pp == task) { - *pp = task->next; - break; - } - pp = &(*pp)->next; - } - xSemaphoreGive(s_mutex); - - free(task); + if (!mutex) + return ESP_ERR_INVALID_STATE; + xSemaphoreTake(mutex, portMAX_DELAY); + watch_slot_t *slot = find_handle(handle); + if (slot) { + atomic_store(&slot->cancel, true); + ts_ssh_service_cancel_observation(slot->config->command_id, slot->config->run_generation); + xTaskNotifyGive(slot->task); } - - ESP_LOGI(TAG, "Stopped log watch task"); - return ESP_OK; + xSemaphoreGive(mutex); + return slot ? ESP_OK : ESP_ERR_NOT_FOUND; } - -bool ts_ssh_log_watch_is_running(const char *var_name) { - if (!var_name || !s_mutex) { +bool ts_ssh_log_watch_pending(ts_ssh_log_watch_handle_t handle) { + if (!mutex) return false; - } - - xSemaphoreTake(s_mutex, portMAX_DELAY); - - ts_ssh_log_watch_task_t *task = s_task_list; - while (task) { - if (strcmp(task->config.var_name, var_name) == 0 && task->is_running) { - xSemaphoreGive(s_mutex); - return true; + xSemaphoreTake(mutex, portMAX_DELAY); + bool found = find_handle(handle) != NULL; + xSemaphoreGive(mutex); + return found; +} +bool ts_ssh_log_watch_is_running(const char *name) { + if (!mutex || !name) + return false; + bool found = false; + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < CONFIG_TS_SSH_LOG_WATCH_MAX; i++) + if (slots[i].config && !strcmp(slots[i].config->var_name, name)) + found = true; + xSemaphoreGive(mutex); + return found; +} +esp_err_t ts_ssh_log_watch_cancel_name(const char *name) { + if (!mutex || !name) + return ESP_ERR_INVALID_ARG; + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < CONFIG_TS_SSH_LOG_WATCH_MAX; i++) + if (slots[i].config && !strcmp(slots[i].config->var_name, name)) { + atomic_store(&slots[i].cancel, true); + ts_ssh_service_cancel_observation(slots[i].config->command_id, + slots[i].config->run_generation); + xTaskNotifyGive(slots[i].task); } - task = task->next; - } - - xSemaphoreGive(s_mutex); - return false; + xSemaphoreGive(mutex); + return ESP_OK; } - void ts_ssh_log_watch_stop_all(void) { - if (!s_mutex) { + if (!mutex) return; - } - - xSemaphoreTake(s_mutex, portMAX_DELAY); - - ts_ssh_log_watch_task_t *task = s_task_list; - while (task) { - ts_ssh_log_watch_task_t *next = task->next; - - task->stop_requested = true; - - // 等待一小段时间让任务退出 - xSemaphoreGive(s_mutex); - vTaskDelay(pdMS_TO_TICKS(200)); - xSemaphoreTake(s_mutex, portMAX_DELAY); - - if (task->is_running && task->task_handle) { - vTaskDelete(task->task_handle); - free(task); + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < CONFIG_TS_SSH_LOG_WATCH_MAX; i++) + if (slots[i].config) { + atomic_store(&slots[i].cancel, true); + ts_ssh_service_cancel_observation(slots[i].config->command_id, + slots[i].config->run_generation); + xTaskNotifyGive(slots[i].task); } - - task = next; - } - - s_task_list = NULL; - xSemaphoreGive(s_mutex); - - ESP_LOGI(TAG, "Stopped all log watch tasks"); + xSemaphoreGive(mutex); } - int ts_ssh_log_watch_get_active_count(void) { - if (!s_mutex) { + if (!mutex) return 0; - } - int count = 0; - xSemaphoreTake(s_mutex, portMAX_DELAY); - - ts_ssh_log_watch_task_t *task = s_task_list; - while (task) { - if (task->is_running) { - count++; - } - task = task->next; - } - - xSemaphoreGive(s_mutex); + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < CONFIG_TS_SSH_LOG_WATCH_MAX; i++) + count += slots[i].config != NULL; + xSemaphoreGive(mutex); return count; } - void ts_ssh_log_watch_list(void) { - if (!s_mutex) { - ESP_LOGI(TAG, "No active log watch tasks"); - return; - } - - xSemaphoreTake(s_mutex, portMAX_DELAY); - - int count = 0; - ts_ssh_log_watch_task_t *task = s_task_list; - - ESP_LOGI(TAG, "=== Active Log Watch Tasks ==="); - while (task) { - if (task->is_running) { - uint32_t elapsed = (xTaskGetTickCount() * portTICK_PERIOD_MS) / 1000 - task->start_time; - ESP_LOGI(TAG, " [%d] var=%s, pattern='%s', elapsed=%us/%us, log=%s", - ++count, task->config.var_name, task->config.ready_pattern, - elapsed, task->config.timeout_sec, task->config.log_file); - } - task = task->next; - } - - if (count == 0) { - ESP_LOGI(TAG, " (none)"); - } - ESP_LOGI(TAG, "=============================="); - - xSemaphoreGive(s_mutex); + ESP_LOGI(TAG, "Active watchers (including cancelling): %d", + ts_ssh_log_watch_get_active_count()); } diff --git a/components/ts_security/src/ts_ssh_probe.c b/components/ts_security/src/ts_ssh_probe.c new file mode 100644 index 0000000..3960c4f --- /dev/null +++ b/components/ts_security/src/ts_ssh_probe.c @@ -0,0 +1,63 @@ +#include "ts_ssh_probe.h" +#include +#include + +bool ts_ssh_shell_quote(const char *input, char *out, size_t cap) { + if (!input || !out || cap < 3) + return false; + size_t n = 0; + out[n++] = '\''; + for (; *input; input++) { + const char *part = *input == '\'' ? "'\\''" : input; + size_t len = *input == '\'' ? 4 : 1; + if (len + 2 >= cap - n) + return false; + memcpy(out + n, part, len); + n += len; + } + out[n++] = '\''; + out[n] = 0; + return true; +} + +bool ts_ssh_log_probe_command(const char *path, const char *ready, const char *fail, char *out, + size_t cap) { + /* Build each quoted value directly in the bounded output, without scratch + * arrays on the 8 KiB SSH worker stack. */ + if (!path || !ready || !fail || cap < 32) + return false; + size_t n = 0; + const char *keys[] = {"p=", "; r=", "; f="}; + const char *values[] = {path, ready, fail}; + for (unsigned i = 0; i < 3; i++) { + size_t len = strlen(keys[i]); + if (len >= cap - n) + return false; + memcpy(out + n, keys[i], len); + n += len; + if (!ts_ssh_shell_quote(values[i], out + n, cap - n)) + return false; + n += strlen(out + n); + } + const char *script = "; if [ ! -f \"$p\" ]; then echo NOTFOUND; " + "elif [ ! -r \"$p\" ]; then exit 2; " + "else if [ -n \"$f\" ]; then grep -qF -- \"$f\" \"$p\"; x=$?; " + "if [ $x -eq 0 ]; then echo FAIL; exit 0; fi; [ $x -eq 1 ] || exit 2; fi; " + "grep -qF -- \"$r\" \"$p\"; x=$?; " + "if [ $x -eq 0 ]; then echo READY; elif [ $x -eq 1 ]; then echo WAITING; " + "else exit 2; fi; fi"; + size_t len = strlen(script); + if (len >= cap - n) + return false; + memcpy(out + n, script, len + 1); + return true; +} + +bool ts_ssh_probe_token(const char *out, const char *token) { + if (!out || !token) + return false; + size_t n = strlen(token); + if (strncmp(out, token, n)) + return false; + return !out[n] || !strcmp(out + n, "\n") || !strcmp(out + n, "\r\n"); +} diff --git a/components/ts_security/src/ts_ssh_service.c b/components/ts_security/src/ts_ssh_service.c new file mode 100644 index 0000000..f1532ad --- /dev/null +++ b/components/ts_security/src/ts_ssh_service.c @@ -0,0 +1,646 @@ +#include "ts_ssh_service.h" +#include "esp_heap_caps.h" +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "ts_keystore.h" +#include "ts_ssh_hosts_config.h" +#include "ts_ssh_log_watch.h" +#include "ts_ssh_probe.h" +#include "ts_variable.h" +#include +#include +#include +#include + +/* Configuration supports 64 commands; preserve that capacity without 64 tasks. */ +typedef struct { + char id[32], host[64], host_id[32], name[32], variable[32]; + char owner_rule[32]; + char instance[96]; /* boot ID + PID + /proc start ticks */ + uint32_t registration, operation; + unsigned recovery_left; + bool deleting, ready_evidence, recovery_worker; + uint16_t port; + unsigned pins; + ts_ssh_service_status_t status; +} service_t; +static service_t *services; /* PSRAM; no allocation in normal rule evaluation */ +static SemaphoreHandle_t mutex, binding_gate; +/* Unique for this boot, fail closed on exhaustion. Never reuse a retired ticket. */ +static uint32_t serial; +static uint32_t ticket(void) { return serial == UINT32_MAX ? 0 : ++serial; } +static bool occupied(const service_t *s) { + return s->deleting || s->pins || s->status.busy || strcmp(s->status.state, "stopped"); +} +static bool complete(service_t *s, uint32_t registration, uint32_t operation) { + if (!s || s->registration != registration || s->operation != operation || !operation) + return false; + s->operation = 0; + s->status.busy = false; + return true; +} +void ts_ssh_binding_lock(void) { + if (binding_gate) + xSemaphoreTake(binding_gate, portMAX_DELAY); +} +void ts_ssh_binding_unlock(void) { + if (binding_gate) + xSemaphoreGive(binding_gate); +} + +esp_err_t ts_ssh_service_init(void) { + if (!binding_gate) + binding_gate = xSemaphoreCreateMutex(); + if (!mutex) + mutex = xSemaphoreCreateMutex(); + if (!services) + services = heap_caps_calloc(TS_SSH_COMMANDS_MAX, sizeof(*services), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + return binding_gate && mutex && services ? ESP_OK : ESP_ERR_NO_MEM; +} +void ts_ssh_service_safe_name(const ts_ssh_command_config_t *cmd, char out[32]) { + unsigned n = 0; + const char *src = cmd->name; + for (unsigned pass = 0; pass < 2 && !n; pass++, src = cmd->id) + for (unsigned i = 0; src[i] && n < 20; i++) + if ((src[i] >= 'a' && src[i] <= 'z') || (src[i] >= 'A' && src[i] <= 'Z') || + (src[i] >= '0' && src[i] <= '9')) + out[n++] = src[i]; + if (!n) { + strcpy(out, "cmd"); + return; + } + out[n] = 0; +} +static service_t *find(const char *id) { + for (unsigned i = 0; i < TS_SSH_COMMANDS_MAX; i++) + if (!strcmp(services[i].id, id)) + return &services[i]; + return NULL; +} +/* Caller holds mutex. Command id plus actual configured target is authoritative; + * a legacy PID-path collision between different ids is rejected. */ +static service_t *register_service(const ts_ssh_command_config_t *cmd, const char *host, + uint16_t port) { + service_t *entry = find(cmd->id), *empty = NULL; + char name[32]; + ts_ssh_service_safe_name(cmd, name); + for (unsigned i = 0; i < TS_SSH_COMMANDS_MAX; i++) { + service_t *s = &services[i]; + if (!s->id[0] && !empty) + empty = s; + if (s != entry && s->id[0] && !strcmp(s->host, host) && s->port == port && + !strcmp(s->name, name)) + return NULL; + } + if (!entry) + entry = empty; + if (!entry) + return NULL; + bool changed = + entry->id[0] && (strcmp(entry->host, host) || entry->port != port || + strcmp(entry->name, name) || strcmp(entry->variable, cmd->var_name)); + if (changed) { + if (occupied(entry)) + return NULL; + memset(entry, 0, sizeof(*entry)); + } + if (entry->deleting) + return NULL; + if (!entry->id[0]) { + entry->registration = ticket(); + if (!entry->registration) return NULL; + entry->status.generation = entry->registration; + strcpy(entry->host_id, cmd->host_id); + snprintf(entry->id, sizeof(entry->id), "%s", cmd->id); + snprintf(entry->host, sizeof(entry->host), "%s", host); + strcpy(entry->name, name); + entry->port = port; + strcpy(entry->variable, cmd->var_name); + strcpy(entry->status.state, "unknown"); + strcpy(entry->status.source, "none"); + } + return entry; +} +esp_err_t ts_ssh_service_pin(const ts_ssh_command_config_t *cmd, const char *host, uint16_t port, uint32_t *registration) { + if (!registration || !mutex || !services) + return ESP_ERR_INVALID_STATE; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = register_service(cmd, host, port ? port : 22); + if (s) { + ++s->pins; + *registration = s->registration; + } + xSemaphoreGive(mutex); + return s ? ESP_OK : ESP_ERR_INVALID_STATE; +} +void ts_ssh_service_unpin(const char *id, uint32_t registration) { + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && s->registration == registration && s->pins) + --s->pins; + xSemaphoreGive(mutex); +} +bool ts_ssh_service_start_admissible(const char *id) { + if (!mutex || !services) + return false; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool allowed = + !s || (!s->deleting && !s->pins && !s->status.busy && + (!strcmp(s->status.state, "stopped") || + (s->status.generation != UINT32_MAX && !strcmp(s->status.source, "none")))); + xSemaphoreGive(mutex); + return allowed; +} +static void state_set(service_t *s, const char *state, const char *source) { + if (strcmp(s->status.state, "unknown") && strcmp(s->status.state, state)) + strcpy(s->status.last_known, s->status.state); + snprintf(s->status.state, sizeof(s->status.state), "%s", state); + snprintf(s->status.source, sizeof(s->status.source), "%s", source); + s->status.confirmed_ms = esp_timer_get_time() / 1000; + /* ts_variable_set is local, synchronous and has no callbacks (notify_change + * currently only logs). Lock order: service -> variable; never inverse. */ + if (s->variable[0]) { + char key[64]; + snprintf(key, sizeof(key), "%s.status", s->variable); + ts_variable_set_string(key, state); + if (!strcmp(state, "ready")) { + snprintf(key, sizeof(key), "%s.ready_time", s->variable); + ts_variable_set_int(key, (int32_t)time(NULL)); + } + } +} +static bool instance_receipt(const char *text, const char *prefix, char out[96]) { + if (!text || strncmp(text, prefix, strlen(prefix))) return false; + const char *v = text + strlen(prefix); + size_t len = strcspn(v, "\r\n"); + if (!len || len >= 96 || strspn(v, "0123456789abcdefABCDEF-:") != len || + (v[len] && strcmp(v + len, "\n") && strcmp(v + len, "\r\n"))) return false; + unsigned separators = 0; + for (size_t i = 0; i < len; ++i) separators += v[i] == ':'; + if (separators != 2) return false; + if (out) { memcpy(out, v, len); out[len] = 0; } + return true; +} +static esp_err_t probe(ts_ssh_session_t session, const char *name, bool stop, bool *running, char instance[96]) { + /* PID file v2 contains exact session leader PID + /proc start time. Group + * signals are used only after both are verified, never PID arithmetic. */ + char *command = heap_caps_malloc(2048, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!command) + return ESP_ERR_NO_MEM; + int n = snprintf(command, 2048, + "d=/tmp/ts_nohup_%s.lock; f=$d/pid; " + "if [ -d \"$d\" ]; then [ -f \"$f\" ] || exit 2; else f=${d%%.lock}.pid; fi; " + "if [ ! -f \"$f\" ]; then echo STOPPED; exit 0; fi; " + "read p stamp < \"$f\" || exit 2; case $p in ''|*[!0-9]*) exit 2;; esac; " + "[ \"$p\" -gt 1 ] || exit 2; " + "if [ ! -r /proc/$p/stat ]; then if kill -0 -- -$p 2>/dev/null; then exit 2; " + "else rm -f -- \"$f\"; [ ! -d \"$d\" ] || rmdir -- \"$d\" || exit 2; echo " + "STOPPED; exit 0; fi; fi; " + "info=$(sed 's/^.*) //' /proc/$p/stat) || exit 2; set -- $info; " + "pg=$3; shift 19; actual=$1; ", + name); + if (n < 0 || n >= 2048) { + free(command); + return ESP_ERR_INVALID_SIZE; + } + const char *tail = stop ? "[ -n \"$stamp\" ] && [ \"$stamp\" = \"$actual\" ] && [ \"$pg\" = " + "\"$p\" ] || exit 2; " + "kill -TERM -- -$p || exit 2; i=0; while [ $i -lt 30 ]; do " + "if ! kill -0 -- -$p 2>/dev/null; then rm -f -- \"$f\"; [ ! -d " + "\"$d\" ] || rmdir -- \"$d\" || exit 2; echo STOPPED; exit 0; fi; " + "sleep 0.1; i=$((i+1)); done; exit 3" + : "if [ -n \"$stamp\" ] && [ \"$stamp\" != \"$actual\" ]; then exit 2; " + "fi; boot=$(cat /proc/sys/kernel/random/boot_id) || exit 2; " + "printf 'RUNNING %s:%s:%s\\n' \"$boot\" \"$p\" \"$actual\""; + if (strlen(tail) >= 2048 - n) { + free(command); + return ESP_ERR_INVALID_SIZE; + } + strcpy(command + n, tail); + ts_ssh_exec_result_t result = {0}; + esp_err_t ret = ts_ssh_exec(session, command, &result); + free(command); + if (ret == ESP_OK) { + if (result.exit_code == 0 && ts_ssh_probe_token(result.stdout_data, "STOPPED")) + *running = false; + else if (!stop && result.exit_code == 0 && instance_receipt(result.stdout_data, "RUNNING ", instance)) + *running = true; + else + ret = ESP_ERR_INVALID_RESPONSE; + } + ts_ssh_exec_result_free(&result); + return ret; +} +esp_err_t ts_ssh_service_begin(const ts_ssh_command_config_t *cmd, ts_ssh_session_t session, + uint32_t *generation) { + if (!services || !mutex || !cmd || !session || !generation) + return ESP_ERR_INVALID_STATE; + *generation = 0; + ts_ssh_binding_lock(); + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = register_service(cmd, ts_ssh_get_host(session), ts_ssh_get_port(session)); + if (!s || s->status.busy || s->status.generation == UINT32_MAX || + !strcmp(s->status.state, "checking") || !strcmp(s->status.state, "starting") || + !strcmp(s->status.state, "stopping")) { + xSemaphoreGive(mutex); + ts_ssh_binding_unlock(); + return ESP_ERR_INVALID_STATE; + } + uint32_t operation = ticket(), registration = s->registration; + if (!operation) { xSemaphoreGive(mutex); ts_ssh_binding_unlock(); return ESP_ERR_INVALID_STATE; } + s->operation = operation; + s->status.busy = true; + s->status.generation = operation; + s->ready_evidence = false; + s->instance[0] = 0; + s->recovery_left = 3; + s->recovery_worker = false; + xSemaphoreGive(mutex); + ts_ssh_binding_unlock(); + bool running = true; + esp_err_t ret = probe(session, s->name, false, &running, NULL); + xSemaphoreTake(mutex, portMAX_DELAY); + if (ret == ESP_OK && !running && s->status.generation == operation) { + *generation = s->status.generation; + state_set(s, "starting", "pid"); + } else { + complete(s, registration, operation); + state_set(s, ret == ESP_OK ? "running" : "unknown", "pid"); + if (ret == ESP_OK) + ret = ESP_ERR_INVALID_STATE; + } + xSemaphoreGive(mutex); + return ret; +} +bool ts_ssh_service_finish(const char *id, uint32_t generation, const char *receipt, + ts_ssh_session_t session) { + char launched_instance[96]; + bool launched = instance_receipt(receipt, "STARTED ", launched_instance); + char identity[96] = {0}, name[32] = {0}; + uint32_t registration = 0; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && s->operation == generation) { + registration = s->registration; + strcpy(name, s->name); + } + xSemaphoreGive(mutex); + if (!registration) return false; + bool running = false; + if (launched) + launched = probe(session, name, false, &running, identity) == ESP_OK && running && + !strcmp(identity, launched_instance); + xSemaphoreTake(mutex, portMAX_DELAY); + s = find(id); + bool current = complete(s, registration, generation) && s->status.generation == generation; + if (current) { + if (launched) strcpy(s->instance, identity); + state_set(s, launched ? "starting" : "unknown", "launch"); + } + xSemaphoreGive(mutex); + return current && launched; +} +/* A log result must bracket its read with verification of the captured instance. */ +esp_err_t ts_ssh_service_verify_instance(const char *id, uint32_t generation, + ts_ssh_session_t session) { + char name[32], expected[96], actual[96] = {0}; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool valid = s && s->status.generation == generation && s->instance[0] && + !s->deleting && strcmp(s->status.state, "stopped") && + strcmp(s->status.state, "stopping") && strcmp(s->status.source, "cancelled"); + if (valid) { strcpy(name, s->name); strcpy(expected, s->instance); } + xSemaphoreGive(mutex); + if (!valid) return ESP_ERR_INVALID_STATE; + bool running = false; + esp_err_t ret = probe(session, name, false, &running, actual); + if (ret == ESP_OK && (!running || strcmp(actual, expected))) ret = ESP_ERR_INVALID_STATE; + return ret; +} +bool ts_ssh_service_observation_valid(const char *id, uint32_t generation) { + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool valid = s && s->status.generation == generation && s->instance[0] && + !s->deleting && strcmp(s->status.source, "cancelled") && + strcmp(s->status.state, "stopped") && strcmp(s->status.state, "stopping"); + xSemaphoreGive(mutex); + return valid; +} +void ts_ssh_service_observe(const char *id, uint32_t generation, const char *state, + const char *var_name) { + if (!mutex || !services || !id) + return; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && generation == s->status.generation && strcmp(s->status.state, "stopping") && + strcmp(s->status.state, "stopped") && strcmp(s->status.source, "cancelled") && s->instance[0]) { + if (!strcmp(state, "ready")) s->ready_evidence = true; + state_set(s, state, "log"); + } + xSemaphoreGive(mutex); +} +static esp_err_t connect_host(const ts_ssh_host_config_t *snapshot, ts_ssh_session_t *session, char **key) { + const ts_ssh_host_config_t host = *snapshot; + esp_err_t ret; + size_t len = 0; + if (!host.keyid[0]) + return ESP_ERR_INVALID_STATE; + ret = ts_keystore_load_private_key(host.keyid, key, &len); + if (ret != ESP_OK) + return ret; + ts_ssh_config_t cfg = TS_SSH_DEFAULT_CONFIG(); + cfg.host = host.host; + cfg.port = host.port; + cfg.username = host.username; + cfg.auth_method = TS_SSH_AUTH_PUBLICKEY; + cfg.auth.key.private_key = (const uint8_t *)*key; + cfg.auth.key.private_key_len = len; + cfg.timeout_ms = 5000; + cfg.max_output_bytes = 128; + ret = ts_ssh_session_create(&cfg, session); + return ret == ESP_OK ? ts_ssh_connect(*session) : ret; +} +static esp_err_t inspect(const char *id, bool stop, uint32_t recovery, ts_ssh_service_status_t *out) { + if (!mutex || !services || !id || !out) + return ESP_ERR_INVALID_ARG; + ts_ssh_command_config_t *cmd = + heap_caps_malloc(sizeof(*cmd), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!cmd) + return ESP_ERR_NO_MEM; + ts_ssh_binding_lock(); + esp_err_t ret = ts_ssh_commands_config_get(id, cmd); + ts_ssh_host_config_t host; + if (ret == ESP_OK && (!cmd->nohup || !cmd->service_mode)) + ret = ESP_ERR_INVALID_STATE; + if (ret == ESP_OK) + ret = ts_ssh_hosts_config_get(cmd->host_id, &host); + if (ret != ESP_OK) { + ts_ssh_binding_unlock(); + free(cmd); + return ret; + } + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = register_service(cmd, host.host, host.port ? host.port : 22); + if (!s) { + xSemaphoreGive(mutex); + ts_ssh_binding_unlock(); + free(cmd); + return ESP_ERR_INVALID_STATE; + } + if (s->deleting || s->status.busy || serial == UINT32_MAX || + (recovery && (s->status.generation != recovery || !s->ready_evidence || + !s->recovery_left || strcmp(s->status.state, "unknown")))) { + *out = s->status; + xSemaphoreGive(mutex); + ts_ssh_binding_unlock(); + free(cmd); + return ESP_ERR_INVALID_STATE; + } + uint32_t operation = ticket(), registration = s->registration; + s->operation = operation; + s->status.busy = true; + if (recovery) --s->recovery_left; + if (stop) { + s->status.generation = operation; + s->ready_evidence = false; + s->recovery_left = 0; + state_set(s, "stopping", "request"); + } + uint32_t generation = s->status.generation; + xSemaphoreGive(mutex); + ts_ssh_binding_unlock(); + if (stop) + ts_ssh_log_watch_cancel_name(cmd->var_name); + ts_ssh_session_t session = NULL; + char *key = NULL; + bool running = true; + char identity[96] = {0}; + ret = connect_host(&host, &session, &key); + if (ret == ESP_OK) + ret = probe(session, s->name, stop, &running, identity); + if (session) + ts_ssh_session_destroy(session); + free(key); + free(cmd); + xSemaphoreTake(mutex, portMAX_DELAY); + if (complete(s, registration, operation) && s->status.generation == generation) { + if (ret != ESP_OK) + state_set(s, "unknown", "pid"); + else if (!running) { + s->ready_evidence = false; + s->instance[0] = 0; + state_set(s, "stopped", "pid"); + } else if (s->ready_evidence && !strcmp(identity, s->instance)) + state_set(s, "ready", "pid+log"); + else if (strcmp(identity, s->instance)) { + s->ready_evidence = false; + s->instance[0] = 0; + state_set(s, "running", "pid"); + } else if (strcmp(s->status.state, "checking") && strcmp(s->status.state, "ready")) + state_set(s, "running", "pid"); + else { + strcpy(s->status.source, "pid"); + s->status.confirmed_ms = esp_timer_get_time() / 1000; + } + } + *out = s->status; + xSemaphoreGive(mutex); + return ret; +} +esp_err_t ts_ssh_service_query(const char *id, ts_ssh_service_status_t *out) { + esp_err_t ret = inspect(id, false, 0, out); + ts_ssh_service_recovery_kick(id); + return ret; +} +esp_err_t ts_ssh_service_stop(const char *id, ts_ssh_service_status_t *out) { + return inspect(id, true, 0, out); +} +bool ts_ssh_service_binding_busy(const char *id) { + if (!mutex || !services) + return true; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool busy = !s || occupied(s); + xSemaphoreGive(mutex); + return busy; +} +bool ts_ssh_service_launch_command(const ts_ssh_command_config_t *cmd, const char *expanded, + char *out, size_t cap) { + char name[32]; + ts_ssh_service_safe_name(cmd, name); + int n = snprintf(out, cap, "mkdir /tmp/ts_nohup_%s.lock || exit 2; nohup setsid sh -c ", name); + if (n < 0 || (size_t)n >= cap || !ts_ssh_shell_quote(expanded, out + n, cap - n)) + return false; + n += strlen(out + n); + int more = snprintf( + out + n, cap - n, + " > /tmp/ts_nohup_%s.log 2>&1 < /dev/null & p=$!; " + "sleep 0.1; info=$(sed 's/^.*) //' /proc/$p/stat) || exit 2; " + "set -- $info; [ \"$3\" = \"$p\" ] || exit 2; shift 19; " + "printf '%%s %%s\\n' \"$p\" \"$1\" > /tmp/ts_nohup_%s.lock/pid || exit 2; " + "boot=$(cat /proc/sys/kernel/random/boot_id) || exit 2; " + "printf 'STARTED %%s:%%s:%%s\\n' \"$boot\" \"$p\" \"$1\"", + name, name); + return more >= 0 && (size_t)more < cap - n; +} + +bool ts_ssh_service_command_protected(const char *id) { + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool protected = s && occupied(s); + xSemaphoreGive(mutex); + if (protected) return true; + ts_ssh_command_config_t *cmd = + heap_caps_malloc(sizeof(*cmd), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!cmd) + return true; + esp_err_t ret = ts_ssh_commands_config_get(id, cmd); + bool busy = ret == ESP_OK && cmd->nohup && cmd->service_mode && ts_ssh_service_binding_busy(id); + free(cmd); + return ret != ESP_OK && ret != ESP_ERR_NOT_FOUND ? true : busy; +} +static bool protect_host(const ts_ssh_command_config_t *cmd, size_t index, void *context) { + bool *busy = context; + if (cmd->nohup && cmd->service_mode && ts_ssh_service_binding_busy(cmd->id)) + *busy = true; + return !*busy; +} +bool ts_ssh_service_host_protected(const char *host_id) { + bool busy = false; + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < TS_SSH_COMMANDS_MAX; ++i) + if (services[i].id[0] && (!host_id || !strcmp(services[i].host_id, host_id)) && occupied(&services[i])) + busy = true; + xSemaphoreGive(mutex); + if (busy) return true; + esp_err_t ret = + host_id ? ts_ssh_commands_config_iterate_by_host(host_id, protect_host, &busy, 0, 0, NULL) + : ts_ssh_commands_config_iterate(protect_host, &busy, 0, 0, NULL); + return busy || ret != ESP_OK; +} + +void ts_ssh_service_cancel_observation(const char *id, uint32_t generation) { + if (!mutex || !services) + return; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && s->status.generation == generation && strcmp(s->status.state, "stopping")) { + s->status.generation = ticket(); + s->ready_evidence = false; + s->recovery_left = 0; + state_set(s, "unknown", "cancelled"); + } + xSemaphoreGive(mutex); +} +bool ts_ssh_service_any_in_use(void) { + if (!mutex || !services) + return false; + bool busy = false; + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < TS_SSH_COMMANDS_MAX; i++) { + service_t *s = &services[i]; + if (s->id[0] && (s->pins || s->status.busy || + (strcmp(s->status.source, "none") && strcmp(s->status.state, "stopped")))) + busy = true; + } + xSemaphoreGive(mutex); + return busy; +} + +/* Called with binding_gate held: deletion is an admission barrier through storage I/O. */ +esp_err_t ts_ssh_service_delete_begin(const char *id, uint32_t *credential) { + *credential = 0; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + esp_err_t ret = ESP_OK; + if (s && occupied(s)) ret = ESP_ERR_INVALID_STATE; + else if (s) { + *credential = ticket(); + if (!*credential) ret = ESP_ERR_INVALID_STATE; + else { s->deleting = true; s->operation = *credential; } + } + xSemaphoreGive(mutex); + return ret; +} +void ts_ssh_service_delete_finish(const char *id, uint32_t credential, bool removed) { + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && s->deleting && complete(s, s->registration, credential)) { + if (removed) memset(s, 0, sizeof(*s)); + else s->deleting = false; + } + xSemaphoreGive(mutex); +} +void ts_ssh_service_forget_stopped(void) { + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < TS_SSH_COMMANDS_MAX; ++i) + if (services[i].id[0] && !occupied(&services[i])) memset(&services[i], 0, sizeof(services[i])); + xSemaphoreGive(mutex); +} +esp_err_t ts_ssh_service_cached(const char *id, ts_ssh_service_status_t *out) { + if (!mutex || !id || !out) return ESP_ERR_INVALID_ARG; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + memset(out, 0, sizeof(*out)); + if (s) *out = s->status; + else { strcpy(out->state, "unknown"); strcpy(out->source, "none"); } + xSemaphoreGive(mutex); + return ESP_OK; +} +/* Three retries per launch, never replenished by query, UI, or recovery success. */ +void ts_ssh_service_recovery_kick(const char *id) { + ts_ssh_log_watch_config_t cfg = {.recovery_only = true, .timeout_sec = 20, .check_interval_ms = 5000}; + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool start = s && !s->recovery_worker && !s->deleting && !s->status.busy && + s->ready_evidence && s->recovery_left && !strcmp(s->status.state, "unknown"); + if (start) { + s->recovery_worker = true; + cfg.run_generation = s->status.generation; + strcpy(cfg.command_id, s->id); strcpy(cfg.host_id, s->host_id); strcpy(cfg.var_name, s->variable); + } + xSemaphoreGive(mutex); + if (start && ts_ssh_log_watch_start(&cfg, NULL) != ESP_OK) { + xSemaphoreTake(mutex, portMAX_DELAY); + s = find(id); + if (s && s->status.generation == cfg.run_generation) s->recovery_worker = false; + xSemaphoreGive(mutex); + } +} +bool ts_ssh_service_recover(const char *id, uint32_t generation) { + ts_ssh_service_status_t status; + inspect(id, false, generation, &status); + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + bool again = s && s->status.generation == generation && s->ready_evidence && + s->recovery_left && !strcmp(s->status.state, "unknown"); + xSemaphoreGive(mutex); + return again; +} +void ts_ssh_service_recovery_done(const char *id, uint32_t generation) { + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && s->status.generation == generation) s->recovery_worker = false; + xSemaphoreGive(mutex); +} + +/* Rule ownership survives queue completion and even missing/replaced templates. */ +void ts_ssh_service_set_owner(const char *id, uint32_t registration, const char *rule) { + xSemaphoreTake(mutex, portMAX_DELAY); + service_t *s = find(id); + if (s && s->registration == registration && s->pins) + snprintf(s->owner_rule, sizeof(s->owner_rule), "%s", rule); + xSemaphoreGive(mutex); +} +bool ts_ssh_service_rule_protected(const char *rule) { + bool busy = false; + xSemaphoreTake(mutex, portMAX_DELAY); + for (unsigned i = 0; i < TS_SSH_COMMANDS_MAX; ++i) + if (services[i].id[0] && !strcmp(services[i].owner_rule, rule) && occupied(&services[i])) + busy = true; + xSemaphoreGive(mutex); + return busy; +} diff --git a/components/ts_security/src/ts_ssh_shell.c b/components/ts_security/src/ts_ssh_shell.c index 08f8444..a2e8b16 100644 --- a/components/ts_security/src/ts_ssh_shell.c +++ b/components/ts_security/src/ts_ssh_shell.c @@ -13,6 +13,7 @@ #include "ts_ssh_client.h" #include "ts_core.h" /* TS_CALLOC_PSRAM */ #include "esp_log.h" +#include "esp_timer.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" @@ -38,6 +39,7 @@ struct ts_ssh_shell_s { LIBSSH2_CHANNEL *channel; /**< SSH 通道 */ ts_shell_config_t config; /**< Shell 配置 */ ts_shell_state_t state; /**< 当前状态 */ + bool close_notified; int exit_code; /**< 退出码 */ /* 回调 */ @@ -102,6 +104,30 @@ static int wait_socket(int sock, LIBSSH2_SESSION *session, int timeout_ms) return select(sock + 1, readfd, writefd, NULL, &timeout); } +/* A libssh2 request left in EAGAIN cannot be replaced by a different request. + * Bound the wait and retire the channel on uncertainty instead of replaying. */ +static bool shell_wait(int sock,LIBSSH2_SESSION *ssh,int64_t deadline) +{ + int64_t left=deadline-esp_timer_get_time(); + if(left<=0)return false; + int ms=(int)((left+999)/1000);if(ms>100)ms=100; + return wait_socket(sock,ssh,ms)>=0 && esp_timer_get_time()channel)return; + /* libssh2 retains ownership only on EAGAIN. Its session owns that channel + * and the client's local-disconnect callbacks make destruction nonwaiting. */ + if(libssh2_channel_free(shell->channel)==LIBSSH2_ERROR_EAGAIN) + ts_ssh_disconnect(shell->ssh_session); + shell->channel=NULL; +} +static void shell_notify_close(ts_ssh_shell_t shell) +{ + if(!shell->close_notified){shell->close_notified=true; + if(shell->close_cb)shell->close_cb(shell->exit_code,shell->close_cb_data);} +} + /* ============================================================================ * 公开 API 实现 * ============================================================================ */ @@ -114,6 +140,7 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, return ESP_ERR_INVALID_ARG; } + *shell_out=NULL; if (!ts_ssh_is_connected(session)) { ESP_LOGE(TAG, "SSH session not connected"); return ESP_ERR_INVALID_STATE; @@ -154,10 +181,11 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, /* 打开通道 */ LIBSSH2_CHANNEL *channel = NULL; int rc; + int64_t deadline=esp_timer_get_time()+10000000; while ((channel = libssh2_channel_open_session(ssh)) == NULL && libssh2_session_last_errno(ssh) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 1000); + if(!shell_wait(sock,ssh,deadline))goto setup_timeout; } if (!channel) { @@ -168,6 +196,7 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, return ESP_FAIL; } + shell->channel=channel; /* 请求 PTY */ const char *term = get_term_string(shell->config.term_type); @@ -177,14 +206,14 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, shell->config.term_width, shell->config.term_height, 0, 0)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 1000); + if(!shell_wait(sock,ssh,deadline))goto setup_timeout; } if (rc != 0) { char *err_msg = NULL; libssh2_session_last_error(ssh, &err_msg, NULL, 0); ESP_LOGE(TAG, "Failed to request PTY: %s", err_msg ? err_msg : "unknown"); - libssh2_channel_free(channel); + shell_release_channel(shell); free(shell); return ESP_FAIL; } @@ -194,14 +223,14 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, /* 启动 Shell */ while ((rc = libssh2_channel_shell(channel)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 1000); + if(!shell_wait(sock,ssh,deadline))goto setup_timeout; } if (rc != 0) { char *err_msg = NULL; libssh2_session_last_error(ssh, &err_msg, NULL, 0); ESP_LOGE(TAG, "Failed to start shell: %s", err_msg ? err_msg : "unknown"); - libssh2_channel_free(channel); + shell_release_channel(shell); free(shell); return ESP_FAIL; } @@ -212,6 +241,18 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, *shell_out = shell; ESP_LOGI(TAG, "Interactive shell opened"); return ESP_OK; +setup_timeout: + shell_release_channel(shell); + ts_ssh_disconnect(session); /* pending open/setup must not survive as a usable session */ + free(shell); + return ESP_ERR_TIMEOUT; +} + +esp_err_t ts_ssh_shell_request_close(ts_ssh_shell_t shell) +{ + if (!shell) return ESP_ERR_INVALID_ARG; + if (shell->state == TS_SHELL_STATE_RUNNING) shell->state = TS_SHELL_STATE_CLOSED; + return ESP_OK; } esp_err_t ts_ssh_shell_close(ts_ssh_shell_t shell) @@ -220,117 +261,51 @@ esp_err_t ts_ssh_shell_close(ts_ssh_shell_t shell) return ESP_ERR_INVALID_ARG; } - if (shell->state != TS_SHELL_STATE_RUNNING) { - return ESP_OK; - } - - LIBSSH2_SESSION *ssh = ts_ssh_get_libssh2_session(shell->ssh_session); - int sock = ts_ssh_get_socket(shell->ssh_session); - - /* 发送 EOF */ - int rc; - while ((rc = libssh2_channel_send_eof(shell->channel)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 100); - } - - /* 等待远程关闭 */ - while ((rc = libssh2_channel_wait_eof(shell->channel)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 100); - } - - /* 关闭通道 */ - while ((rc = libssh2_channel_close(shell->channel)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 100); - } - - /* 获取退出码 */ - if (rc == 0) { - shell->exit_code = libssh2_channel_get_exit_status(shell->channel); - } - - /* 调用关闭回调 */ - if (shell->close_cb) { - shell->close_cb(shell->exit_code, shell->close_cb_data); - } - - libssh2_channel_free(shell->channel); - shell->channel = NULL; - shell->state = TS_SHELL_STATE_CLOSED; - - ESP_LOGI(TAG, "Shell closed with exit code: %d", shell->exit_code); - - /* 释放结构 */ + /* EOF/ERROR changes state, not ownership. All allocated handles are + * consumed here; callers clear their handle after this call. */ + if(shell->channel && shell->state==TS_SHELL_STATE_RUNNING) + shell->exit_code=libssh2_channel_get_exit_status(shell->channel); + shell->state=TS_SHELL_STATE_CLOSED; + shell_release_channel(shell); + shell_notify_close(shell); free(shell); return ESP_OK; } -esp_err_t ts_ssh_shell_write(ts_ssh_shell_t shell, - const char *data, size_t len, - size_t *written) +esp_err_t ts_ssh_shell_write(ts_ssh_shell_t shell,const char *data,size_t len,size_t *written) { - if (!shell || !data || len == 0) { - return ESP_ERR_INVALID_ARG; - } - - if (shell->state != TS_SHELL_STATE_RUNNING) { - return ESP_ERR_INVALID_STATE; - } - - LIBSSH2_SESSION *ssh = ts_ssh_get_libssh2_session(shell->ssh_session); - int sock = ts_ssh_get_socket(shell->ssh_session); - - size_t total_written = 0; - while (total_written < len) { - int rc = libssh2_channel_write(shell->channel, data + total_written, - len - total_written); - if (rc > 0) { - total_written += rc; - } else if (rc == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 100); - } else { - ESP_LOGE(TAG, "Write error: %d", rc); - return ESP_FAIL; - } - } - - if (written) { - *written = total_written; + if(written)*written=0; + if(!shell || !data || !len)return ESP_ERR_INVALID_ARG; + if(shell->state!=TS_SHELL_STATE_RUNNING)return ESP_ERR_INVALID_STATE; + LIBSSH2_SESSION *ssh=ts_ssh_get_libssh2_session(shell->ssh_session); + int sock=ts_ssh_get_socket(shell->ssh_session); + int64_t deadline=esp_timer_get_time()+1000000; + size_t total=0; + while(totalchannel,data+total,len-total); + if(rc>0){total+=rc;if(written)*written=total;} + else if(rc==LIBSSH2_ERROR_EAGAIN && shell_wait(sock,ssh,deadline))continue; + else {shell->state=TS_SHELL_STATE_ERROR;return rc==LIBSSH2_ERROR_EAGAIN?ESP_ERR_TIMEOUT:ESP_FAIL;} + if(total=deadline){shell->state=TS_SHELL_STATE_ERROR;return ESP_ERR_TIMEOUT;} } - return ESP_OK; } -esp_err_t ts_ssh_shell_read(ts_ssh_shell_t shell, - char *buffer, size_t buffer_size, - size_t *read_len) +esp_err_t ts_ssh_shell_read(ts_ssh_shell_t shell,char *buffer,size_t size,size_t *read_len) { - if (!shell || !buffer || buffer_size == 0) { - return ESP_ERR_INVALID_ARG; - } - - if (shell->state != TS_SHELL_STATE_RUNNING) { - if (read_len) *read_len = 0; + if(read_len)*read_len=0; + if(!shell || !buffer || !size)return ESP_ERR_INVALID_ARG; + if(shell->state!=TS_SHELL_STATE_RUNNING)return ESP_ERR_INVALID_STATE; + int rc=libssh2_channel_read(shell->channel,buffer,size); + if(rc>0){if(read_len)*read_len=rc;return ESP_OK;} + if((rc==0 || rc==LIBSSH2_ERROR_EAGAIN) && libssh2_channel_eof(shell->channel)){ + shell->state=TS_SHELL_STATE_CLOSED; + shell->exit_code=libssh2_channel_get_exit_status(shell->channel); return ESP_ERR_INVALID_STATE; } - - int rc = libssh2_channel_read(shell->channel, buffer, buffer_size); - - if (rc > 0) { - if (read_len) *read_len = rc; - return ESP_OK; - } else if (rc == 0) { - /* EOF */ - if (read_len) *read_len = 0; - shell->state = TS_SHELL_STATE_CLOSED; - shell->exit_code = libssh2_channel_get_exit_status(shell->channel); - return ESP_ERR_INVALID_STATE; - } else if (rc == LIBSSH2_ERROR_EAGAIN) { - if (read_len) *read_len = 0; - return ESP_ERR_TIMEOUT; - } else { - if (read_len) *read_len = 0; - return ESP_FAIL; - } + if(rc==0 || rc==LIBSSH2_ERROR_EAGAIN)return ESP_ERR_TIMEOUT; /* no data, not EOF */ + shell->state=TS_SHELL_STATE_ERROR; + return ESP_FAIL; } esp_err_t ts_ssh_shell_set_output_cb(ts_ssh_shell_t shell, @@ -359,124 +334,40 @@ esp_err_t ts_ssh_shell_set_close_cb(ts_ssh_shell_t shell, esp_err_t ts_ssh_shell_poll(ts_ssh_shell_t shell) { - if (!shell) { - return ESP_ERR_INVALID_ARG; - } - - if (shell->state != TS_SHELL_STATE_RUNNING) { - return ESP_ERR_INVALID_STATE; - } - - /* 检查通道是否关闭 */ - if (libssh2_channel_eof(shell->channel)) { - shell->state = TS_SHELL_STATE_CLOSED; - shell->exit_code = libssh2_channel_get_exit_status(shell->channel); - if (shell->close_cb) { - shell->close_cb(shell->exit_code, shell->close_cb_data); - } - return ESP_ERR_INVALID_STATE; - } - - /* 读取可用数据 */ - int rc = libssh2_channel_read(shell->channel, shell->read_buffer, - sizeof(shell->read_buffer)); - - if (rc > 0) { - if (shell->output_cb) { - shell->output_cb(shell->read_buffer, rc, shell->output_cb_data); - } - return ESP_OK; - } else if (rc == LIBSSH2_ERROR_EAGAIN) { - return ESP_ERR_TIMEOUT; - } else if (rc == 0) { - shell->state = TS_SHELL_STATE_CLOSED; - shell->exit_code = libssh2_channel_get_exit_status(shell->channel); - if (shell->close_cb) { - shell->close_cb(shell->exit_code, shell->close_cb_data); - } - return ESP_ERR_INVALID_STATE; - } else { - return ESP_FAIL; - } + if(!shell)return ESP_ERR_INVALID_ARG; + size_t n=0;esp_err_t ret=ts_ssh_shell_read(shell,shell->read_buffer,sizeof(shell->read_buffer),&n); + if(n && shell->output_cb)shell->output_cb(shell->read_buffer,n,shell->output_cb_data); + if(shell->state==TS_SHELL_STATE_CLOSED || shell->state==TS_SHELL_STATE_ERROR)shell_notify_close(shell); + return ret; } -esp_err_t ts_ssh_shell_run(ts_ssh_shell_t shell, - ts_shell_output_cb_t output_cb, - ts_shell_input_cb_t input_cb, - void *user_data) +esp_err_t ts_ssh_shell_run(ts_ssh_shell_t shell,ts_shell_output_cb_t output_cb, + ts_shell_input_cb_t input_cb,void *data) { - if (!shell || !output_cb || !input_cb) { - return ESP_ERR_INVALID_ARG; - } - - if (shell->state != TS_SHELL_STATE_RUNNING) { - return ESP_ERR_INVALID_STATE; - } - - LIBSSH2_SESSION *ssh = ts_ssh_get_libssh2_session(shell->ssh_session); - int sock = ts_ssh_get_socket(shell->ssh_session); - - while (shell->state == TS_SHELL_STATE_RUNNING) { - bool activity = false; - - /* 检查本地输入(优先处理,提高响应性) */ - size_t input_len = 0; - const char *input = input_cb(&input_len, user_data); - if (input && input_len > 0) { - activity = true; - size_t written = 0; - while (written < input_len) { - int rc = libssh2_channel_write(shell->channel, input + written, - input_len - written); - if (rc > 0) { - written += rc; - } else if (rc == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 10); - } else { - shell->state = TS_SHELL_STATE_ERROR; - return ESP_FAIL; - } - } - } - - /* 持续读取远程数据直到没有更多数据 */ - int rc; + if(!shell || !output_cb || !input_cb)return ESP_ERR_INVALID_ARG; + if(shell->state!=TS_SHELL_STATE_RUNNING)return ESP_ERR_INVALID_STATE; + while(shell->state==TS_SHELL_STATE_RUNNING){ + size_t len=0;const char *input=input_cb(&len,data); + if(shell->state!=TS_SHELL_STATE_RUNNING)break; + if(input && len){esp_err_t ret=ts_ssh_shell_write(shell,input,len,NULL);if(ret!=ESP_OK)return ret;} + bool activity = len != 0; + size_t n; do { - rc = libssh2_channel_read(shell->channel, shell->read_buffer, - sizeof(shell->read_buffer)); - if (rc > 0) { - activity = true; - output_cb(shell->read_buffer, rc, user_data); - } else if (rc == 0 || libssh2_channel_eof(shell->channel)) { - /* 远程关闭 */ - shell->exit_code = libssh2_channel_get_exit_status(shell->channel); - shell->state = TS_SHELL_STATE_CLOSED; - return ESP_OK; - } - } while (rc > 0); /* 继续读取直到 EAGAIN */ - - if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { - /* 真正的错误 */ - shell->state = TS_SHELL_STATE_ERROR; - return ESP_FAIL; - } - - /* 只在没有活动时短暂等待,避免 CPU 空转 */ - if (!activity) { - wait_socket(sock, ssh, 10); /* 减少等待时间到 10ms */ - } - } - - shell->exit_code = libssh2_channel_get_exit_status(shell->channel); - shell->state = TS_SHELL_STATE_CLOSED; - - return ESP_OK; + n = 0; + esp_err_t ret = ts_ssh_shell_read(shell, shell->read_buffer, sizeof(shell->read_buffer), &n); + if (n) { output_cb(shell->read_buffer, n, data); activity = true; } + if (shell->state == TS_SHELL_STATE_CLOSED) return ESP_OK; + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) return ret; + } while (n); /* preserve CLI's existing drain-until-no-data cadence */ + if(!activity)wait_socket(ts_ssh_get_socket(shell->ssh_session),ts_ssh_get_libssh2_session(shell->ssh_session),10); + } + return shell->state==TS_SHELL_STATE_CLOSED?ESP_OK:ESP_FAIL; } esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t shell, uint16_t width, uint16_t height) { - if (!shell) { + if (!shell || !width || !height) { return ESP_ERR_INVALID_ARG; } @@ -488,13 +379,15 @@ esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t shell, int sock = ts_ssh_get_socket(shell->ssh_session); int rc; + int64_t deadline=esp_timer_get_time()+1000000; while ((rc = libssh2_channel_request_pty_size(shell->channel, width, height)) == LIBSSH2_ERROR_EAGAIN) { - wait_socket(sock, ssh, 100); + if(!shell_wait(sock,ssh,deadline)){shell->state=TS_SHELL_STATE_ERROR;return ESP_ERR_TIMEOUT;} } if (rc != 0) { ESP_LOGW(TAG, "Failed to resize PTY: %d", rc); + if(rc!=LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED)shell->state=TS_SHELL_STATE_ERROR; return ESP_FAIL; } diff --git a/components/ts_webui/CMakeLists.txt b/components/ts_webui/CMakeLists.txt index 1e10d88..0fd6e09 100644 --- a/components/ts_webui/CMakeLists.txt +++ b/components/ts_webui/CMakeLists.txt @@ -4,6 +4,8 @@ idf_component_register( "src/ts_webui_api.c" "src/ts_webui_ws.c" "src/ts_ws_subscriptions.c" + "src/ts_ws_transport.c" + "src/ts_ws_operation.c" INCLUDE_DIRS "include" REQUIRES @@ -66,6 +68,6 @@ if(EXISTS "${WEB_SRC_DIR}") add_custom_target(optimize_web ALL DEPENDS ${FINAL_STAMP}) # 从优化后的构建目录创建 SPIFFS 镜像 - spiffs_create_partition_image(www ${WEB_BUILD_DIR} FLASH_IN_PROJECT) + spiffs_create_partition_image(www ${WEB_BUILD_DIR} FLASH_IN_PROJECT DEPENDS optimize_web) endif() diff --git a/components/ts_webui/include/ts_ws_operation.h b/components/ts_webui/include/ts_ws_operation.h new file mode 100644 index 0000000..af7019e --- /dev/null +++ b/components/ts_webui/include/ts_ws_operation.h @@ -0,0 +1,61 @@ +#pragma once +/* Internal lifecycle; all returned operation pointers carry a reference. */ +#include "ts_ws_transport.h" +typedef enum { TS_WS_OP_SHELL, TS_WS_OP_EXEC, TS_WS_OP_KINDS } ts_ws_op_kind_t; +typedef enum { OP_FREE, OP_STARTING, OP_OPEN, OP_CLOSING, OP_FINALIZING, + OP_TERMINAL_PENDING, OP_TERMINAL_SETTLED, OP_RECLAIMING } ts_ws_op_phase_t; +typedef struct ts_ws_operation ts_ws_operation_t; +typedef struct { + ts_ws_operation_t *op; + uint64_t sequence; /* single producer order within this operation */ + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; + unsigned count; +} ts_ws_output_ticket_t; +typedef struct { + ts_ws_op_phase_t phase; + uint64_t identity, tickets, finished, registered, settled, finalizers, duplicates; + unsigned refs, executors, preparing, unsettled, terminals; + bool failed; +} ts_ws_op_stats_t; +void ts_ws_op_enable(void); +void ts_ws_op_stop_admission(void); +bool ts_ws_op_busy(void); +ts_ws_operation_t *ts_ws_op_create(ts_ws_op_kind_t kind, ts_ws_peer_t peer, esp_err_t *error); +void ts_ws_op_bind(ts_ws_operation_t *op, void *data, void (*destroy)(void *)); +void *ts_ws_op_data(ts_ws_operation_t *op); /* caller owns a reference */ +uint32_t ts_ws_op_id(ts_ws_operation_t *op); +ts_ws_operation_t *ts_ws_op_acquire(ts_ws_op_kind_t kind, uint32_t id); +void ts_ws_op_retain(ts_ws_operation_t *op); +void ts_ws_op_release(ts_ws_operation_t *op); +void ts_ws_op_executor_take(ts_ws_operation_t *op); +void ts_ws_op_executor_done(ts_ws_operation_t *op); +bool ts_ws_op_executing(ts_ws_operation_t *op); +bool ts_ws_op_open(ts_ws_operation_t *op); +bool ts_ws_op_is_open(ts_ws_operation_t *op); +bool ts_ws_op_starting(ts_ws_operation_t *op); +ts_ws_peer_t ts_ws_op_peer(ts_ws_operation_t *op); +void ts_ws_op_discard(ts_ws_operation_t *op); /* unaccepted creation */ +bool ts_ws_op_output_begin(ts_ws_operation_t *op, ts_ws_output_ticket_t *ticket); +void ts_ws_op_output_finish(ts_ws_output_ticket_t *ticket, const char *json); +/* winner owns a close builder until close_finish, before any encoding */ +bool ts_ws_op_close_begin(ts_ws_operation_t *op); +void ts_ws_op_close_finish(ts_ws_operation_t *op, const char *json); +void ts_ws_op_poll(void); /* existing subscription worker, no new task */ +void ts_ws_op_stats(ts_ws_op_kind_t kind, ts_ws_op_stats_t *stats); + +void ts_ws_op_set_maintenance(ts_ws_operation_t *op,bool (*maintain)(void *)); +bool ts_ws_op_needs_tick(void); + +/* Control ownership is separate from observation state. Page controls never use + * wildcard acquire. Owner shutdown and exact-ID business cancellation differ. */ +ts_ws_operation_t *ts_ws_op_shell_control(ts_ws_peer_t peer); +ts_ws_operation_t *ts_ws_op_shell_owner(void); +ts_ws_operation_t *ts_ws_op_shell_connection(ts_ws_peer_t peer); +typedef enum { OP_STOP_NONE=0, OP_STOP_USER=1, OP_STOP_TIMEOUT=2, OP_STOP_MATCH=4 } ts_ws_stop_reason_t; +typedef enum { OP_BUSINESS_PREPARING, OP_BUSINESS_SUBMITTED, OP_BUSINESS_ENDED } ts_ws_business_phase_t; +ts_ws_operation_t *ts_ws_op_cancel_exec(uint32_t id); +bool ts_ws_op_request_stop(ts_ws_operation_t *op,ts_ws_stop_reason_t reason); +bool ts_ws_op_cancelled(void *context); +bool ts_ws_op_claim_submit(ts_ws_operation_t *op); +ts_ws_stop_reason_t ts_ws_op_business_end(ts_ws_operation_t *op,bool deadline); +bool ts_ws_op_business_running(ts_ws_operation_t *op); diff --git a/components/ts_webui/include/ts_ws_subscriptions.h b/components/ts_webui/include/ts_ws_subscriptions.h index 2248018..2f872ac 100644 --- a/components/ts_webui/include/ts_ws_subscriptions.h +++ b/components/ts_webui/include/ts_ws_subscriptions.h @@ -9,6 +9,7 @@ #pragma once #include "esp_err.h" +#include "ts_ws_transport.h" #include "ts_event.h" #include "cJSON.h" #include @@ -27,33 +28,35 @@ esp_err_t ts_ws_subscriptions_init(void); /** * @brief 反初始化订阅管理器 */ -void ts_ws_subscriptions_deinit(void); +esp_err_t ts_ws_subscriptions_deinit(void); +esp_err_t ts_ws_subscriptions_pause(void); +esp_err_t ts_ws_subscriptions_drain(void); /** * @brief 处理订阅请求 * - * @param fd 客户端文件描述符 + * @param peer 已登记的 HTTPD 会话身份(不能只传 fd) * @param topic 订阅主题 (e.g., "device.status", "ota.progress") * @param params JSON 参数对象 (可选) * @return ESP_OK on success */ -esp_err_t ts_ws_subscribe(int fd, const char *topic, cJSON *params); +esp_err_t ts_ws_subscribe(ts_ws_peer_t peer, const char *topic, cJSON *params); /** * @brief 处理取消订阅请求 * - * @param fd 客户端文件描述符 + * @param peer 已登记的 HTTPD 会话身份(不能只传 fd) * @param topic 订阅主题 * @return ESP_OK on success */ -esp_err_t ts_ws_unsubscribe(int fd, const char *topic); +esp_err_t ts_ws_unsubscribe(ts_ws_peer_t peer, const char *topic); /** * @brief 客户端断开连接时清理订阅 * - * @param fd 客户端文件描述符 + * @param peer 已登记的 HTTPD 会话身份(不能只传 fd) */ -void ts_ws_client_disconnected(int fd); +void ts_ws_client_disconnected(ts_ws_peer_t peer); /** * @brief 广播数据到订阅了特定 topic 的客户端 @@ -66,3 +69,7 @@ void ts_ws_broadcast_to_topic(const char *topic, cJSON *data); #ifdef __cplusplus } #endif + +/* Stable existing worker wake; does not allocate or start a new task. */ +void ts_ws_subscriptions_wake(void); +bool ts_ws_subscriptions_in_context(void); diff --git a/components/ts_webui/include/ts_ws_transport.h b/components/ts_webui/include/ts_ws_transport.h new file mode 100644 index 0000000..6f4ee12 --- /dev/null +++ b/components/ts_webui/include/ts_ws_transport.h @@ -0,0 +1,131 @@ +#pragma once +/* Internal bounded delivery path. Session mutation and send execute in HTTPD. */ +#include "esp_http_server.h" +#include "cJSON.h" +#include +#include +#define TS_WS_TOPIC_TX_SLOTS 32 +#define TS_WS_TX_SLOTS (TS_WS_TOPIC_TX_SLOTS + TS_WS_CONNECTIONS) +#define TS_WS_MESSAGE_SLOTS 8 +#define TS_WS_POWER_TRANSITIONS 4 +#define TS_WS_POWER_SLOTS (TS_WS_POWER_TRANSITIONS + 1) +#define TS_WS_POWER_BYTES 1024 +#define TS_WS_POWER_BUDGET (TS_WS_POWER_SLOTS * TS_WS_POWER_BYTES) +#define TS_WS_QUEUE_RETRIES 300 /* 100 ms backoff, bounded SDK admission retries */ +#define TS_WS_ALL_MESSAGE_SLOTS (TS_WS_MESSAGE_SLOTS + 2 + TS_WS_POWER_SLOTS) +#define TS_WS_RESULT_TX_END (TS_WS_TX_SLOTS + 2 * TS_WS_CONNECTIONS) +#define TS_WS_ALL_TX_SLOTS (TS_WS_RESULT_TX_END + TS_WS_POWER_SLOTS * TS_WS_CONNECTIONS) +#define TS_WS_FRAME_BYTES 32768 +#define TS_WS_LEGACY_BYTES (512 * 1024) +#define TS_WS_TOTAL_BYTES (1024 * 1024) +#ifdef CONFIG_TS_WEBUI_WS_MAX_CLIENTS +#define TS_WS_CONNECTIONS CONFIG_TS_WEBUI_WS_MAX_CLIENTS +#else +#define TS_WS_CONNECTIONS 8 +#endif + +typedef struct { + httpd_handle_t server; + uint64_t epoch, connection; + int fd; +} ts_ws_peer_t; +typedef struct ts_ws_message ts_ws_message_t; +typedef bool (*ts_ws_delivery_check_t)(uint64_t revision, uint64_t delivery); +typedef void (*ts_ws_delivery_done_t)(uint64_t revision, uint64_t delivery, esp_err_t result); +typedef void (*ts_ws_closed_t)(ts_ws_peer_t peer); +esp_err_t ts_ws_transport_start(httpd_handle_t server, ts_ws_closed_t closed); +esp_err_t ts_ws_transport_stop(httpd_handle_t server, uint32_t timeout_ms); +bool ts_ws_transport_in_context(void); +esp_err_t ts_ws_peer_open(httpd_req_t *req, ts_ws_peer_t *peer); +/* HTTPD owner only. Values, not bare fd, cross task boundaries. */ +void ts_ws_peer_close(ts_ws_peer_t peer); +bool ts_ws_peer_get(httpd_handle_t server, int fd, ts_ws_peer_t *peer); +bool ts_ws_peer_equal(ts_ws_peer_t a, ts_ws_peer_t b); +unsigned ts_ws_transport_capacity(void); +ts_ws_message_t *ts_ws_message_json(const char *topic, const cJSON *data, int64_t timestamp); +ts_ws_message_t *ts_ws_message_text(const char *text, size_t len); +void ts_ws_message_release(ts_ws_message_t *message); +/* ESP_OK means local acceptance. Each accepted target settles once via done, + * including later queue failure, stale/canceled target and socket failure. + * A synchronous rejection never calls done. Message origin selects its pool. */ +esp_err_t ts_ws_transport_submit(ts_ws_peer_t peer, ts_ws_message_t *message, + uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done); +/* Compatibility bridge for existing global/stream senders; never coalesces. */ +esp_err_t ts_ws_transport_send(httpd_handle_t server, int fd, const httpd_ws_frame_t *frame); + +void ts_ws_transport_stopped(httpd_handle_t server); +esp_err_t ts_ws_transport_broadcast(const httpd_ws_frame_t *frame); + +void ts_ws_peer_log_level(ts_ws_peer_t peer, int level); +esp_err_t ts_ws_transport_log(const httpd_ws_frame_t *frame, int level); +unsigned ts_ws_message_capacity(void); + +/* cJSON 1.7's AddItemReferenceToObject loses its newly allocated reference if + * key duplication fails. Own that reference explicitly; keys here are static. */ +static inline bool ts_ws_json_reference(cJSON *object, const char *key, const cJSON *data) +{ + if (!object || !data) return false; + cJSON *ref = cJSON_CreateNull(); + if (!ref) return false; + *ref = *data; + ref->next = ref->prev = NULL; + ref->string = NULL; + ref->type = (ref->type & ~cJSON_StringIsConst) | cJSON_IsReference; + if (cJSON_AddItemToObjectCS(object, key, ref)) return true; + cJSON_Delete(ref); + return false; +} + +typedef struct { + uint64_t queued, attempts, success, failed, stale, rejected; + uint64_t settled, power_accepted, power_rejected, power_settled, power_failed; + uint32_t bytes, bytes_high, jobs, jobs_high; + int64_t max_send_us; +} ts_ws_transport_stats_t; +void ts_ws_transport_get_stats(ts_ws_transport_stats_t *stats); + +/* Deterministic host barriers; compiled out in firmware. */ +#ifndef TS_WS_TEST_POINT +#define TS_WS_TEST_POINT(name) ((void)0) +#endif + +esp_err_t ts_ws_transport_quiesce(httpd_handle_t server, uint32_t timeout_ms); + +void ts_ws_transport_flush(void); +bool ts_ws_transport_needs_flush(void); +void ts_ws_transport_cancel_topics(void); + +/* A bounded reservation owns actual payload bytes and destination descriptors. + * No API collection / accepted result producer may start before it succeeds. */ +#define TS_WS_RESERVATION_TARGETS ((TS_WS_CONNECTIONS > TS_WS_TOPIC_TX_SLOTS) ? TS_WS_CONNECTIONS : TS_WS_TOPIC_TX_SLOTS) +typedef struct { + ts_ws_message_t *message; + unsigned count; + int slots[TS_WS_RESERVATION_TARGETS]; +} ts_ws_reservation_t; +esp_err_t ts_ws_reserve(const ts_ws_peer_t *peers, unsigned count, bool result, + size_t bytes, ts_ws_reservation_t *reservation); +bool ts_ws_reserved_json(ts_ws_reservation_t *r, const char *topic, const cJSON *data, int64_t timestamp); +esp_err_t ts_ws_reserved_text(ts_ws_reservation_t *r, const char *text); +esp_err_t ts_ws_reserved_submit(ts_ws_reservation_t *r, unsigned index, + uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done); +void ts_ws_reservation_release(ts_ws_reservation_t *r); +unsigned ts_ws_peer_snapshot(ts_ws_peer_t *peers, unsigned capacity); + +/* Preserve global result recipients at completion, with capacity owned at admission. */ +esp_err_t ts_ws_result_reserve(size_t bytes, ts_ws_reservation_t *r); +esp_err_t ts_ws_result_broadcast(ts_ws_reservation_t *r, const char *text); + +uint32_t ts_ws_transport_retry_ms(void); + +/* Fixed power payloads and exclusive descriptors/byte budget. Tick traffic has + * its own slot; neither ticks nor ordinary logs consume transition capacity. + * Snapshot recipients at admission; no coalescing or re-broadcast on retry. */ +esp_err_t ts_ws_power_reserve(bool tick, ts_ws_reservation_t *r); +esp_err_t ts_ws_power_publish(ts_ws_reservation_t *r, const char *text); + +esp_err_t ts_ws_result_publish(ts_ws_reservation_t *r,const ts_ws_peer_t *peers,unsigned count); + +/* Bind an original terminal recipient before transferring its reserved target. */ +esp_err_t ts_ws_reserved_target(ts_ws_reservation_t *r, unsigned index, ts_ws_peer_t peer, + uint64_t revision, uint64_t delivery, ts_ws_delivery_done_t done); diff --git a/components/ts_webui/src/ts_webui.c b/components/ts_webui/src/ts_webui.c index 3184c7b..80abb4a 100644 --- a/components/ts_webui/src/ts_webui.c +++ b/components/ts_webui/src/ts_webui.c @@ -87,8 +87,10 @@ esp_err_t ts_webui_deinit(void) { if (!s_initialized) return ESP_OK; - ts_webui_stop(); - ts_http_server_deinit(); + esp_err_t ret = ts_webui_stop(); + if (ret != ESP_OK) return ret; + ret = ts_http_server_deinit(); + if (ret != ESP_OK) return ret; s_initialized = false; return ESP_OK; @@ -96,7 +98,7 @@ esp_err_t ts_webui_deinit(void) esp_err_t ts_webui_start(void) { - if (s_running) return ESP_OK; + if (s_running && ts_http_server_get_handle() && !ts_http_server_is_stopping()) return ESP_OK; if (!s_initialized) { esp_err_t ret = ts_webui_init(); if (ret != ESP_OK) return ret; @@ -120,6 +122,8 @@ esp_err_t ts_webui_start(void) ret = ts_webui_ws_init(); if (ret != ESP_OK) { TS_LOGW(TAG, "WebSocket init failed"); + esp_err_t stop_ret = ts_http_server_stop(); + return stop_ret != ESP_OK ? stop_ret : ret; } #endif @@ -140,9 +144,9 @@ esp_err_t ts_webui_start(void) esp_err_t ts_webui_stop(void) { - if (!s_running) return ESP_OK; - ts_http_server_stop(); + esp_err_t ret = ts_http_server_stop(); + if (ret != ESP_OK) return ret; s_running = false; TS_LOGI(TAG, "WebUI stopped"); @@ -151,5 +155,5 @@ esp_err_t ts_webui_stop(void) bool ts_webui_is_running(void) { - return s_running; + return s_running && ts_http_server_get_handle() && !ts_http_server_is_stopping(); } diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c index d0a1abd..b79cb47 100644 --- a/components/ts_webui/src/ts_webui_ws.c +++ b/components/ts_webui/src/ts_webui_ws.c @@ -13,6 +13,12 @@ #include "ts_ssh_shell.h" #include "ts_keystore.h" #include "ts_ws_subscriptions.h" +#include "ts_ws_transport.h" +#include "ts_ws_operation.h" +#include "freertos/timers.h" +#include +#include +#include "esp_timer.h" // ts_var.h 已废弃,统一使用 ts_variable.h(ts_automation 变量系统) #include "ts_variable.h" #include "esp_http_server.h" @@ -25,6 +31,7 @@ #include #include #include +#include #define TAG "webui_ws" @@ -43,6 +50,7 @@ /* SSH Shell 输出缓冲区大小 */ #define SSH_OUTPUT_BUF_SIZE 2048 +#define SSH_POLL_STACK_SIZE 8192 typedef enum { WS_CLIENT_TYPE_EVENT, // 普通事件订阅客户端 @@ -52,15 +60,17 @@ typedef enum { } ws_client_type_t; typedef struct { - bool active; - int fd; - httpd_handle_t hd; - ws_client_type_t type; - ts_log_level_t log_min_level; // 日志客户端的最小级别过滤 + atomic_bool active; + ts_ws_peer_t peer; /* HTTPD owner writes the connection registry */ + atomic_int fd; + _Atomic(httpd_handle_t) hd; + _Atomic(ws_client_type_t) type; + _Atomic(ts_log_level_t) log_min_level; // 日志客户端的最小级别过滤 } ws_client_t; static ws_client_t s_clients[MAX_WS_CLIENTS]; -static httpd_handle_t s_server = NULL; +static _Atomic(httpd_handle_t) s_server = NULL; +static atomic_bool s_ws_stopping; static SemaphoreHandle_t s_terminal_mutex = NULL; static int s_terminal_client_fd = -1; // 当前终端会话的 fd @@ -69,35 +79,48 @@ static char *s_terminal_output_buf = NULL; static size_t s_terminal_output_len = 0; static SemaphoreHandle_t s_output_mutex = NULL; -/* SSH Shell 会话状态 */ -static ts_ssh_session_t s_ssh_session = NULL; -static ts_ssh_shell_t s_ssh_shell = NULL; -static int s_ssh_client_fd = -1; -static TaskHandle_t s_ssh_poll_task = NULL; -static volatile bool s_ssh_running = false; - -/* SSH Exec 流式执行状态 */ -static ts_ssh_session_t s_exec_session = NULL; -static TaskHandle_t s_exec_task = NULL; -static volatile bool s_exec_running = false; -static volatile bool s_exec_cancel_requested = false; /* 实时匹配触发的取消请求 */ -static volatile uint32_t s_exec_session_id = 0; -static TimerHandle_t s_exec_timeout_timer = NULL; /* 超时定时器 */ +/* Business resources belong to the operation held by task args and borrowers. */ +typedef struct { + ts_ws_operation_t *op; + ts_ssh_session_t session; + ts_ssh_shell_t shell; + SemaphoreHandle_t io; + atomic_bool disconnect_requested; +} ssh_shell_context_t; /* 电压保护事件处理器句柄 */ static ts_event_handler_handle_t s_power_event_handle = NULL; /* 日志回调句柄 */ static ts_log_callback_handle_t s_log_callback_handle = NULL; -static volatile bool s_log_streaming_enabled = false; +static atomic_bool s_log_streaming_enabled = false; /* 日志级别名称映射 */ static const char *s_level_names[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"}; /* 前向声明 */ +static void exec_retry_timer_drain(void); static void update_log_stream_state(void); +esp_err_t ts_webui_log_stream_enable(bool enable); +esp_err_t ts_webui_ws_stop(httpd_handle_t server); +void ts_webui_ws_stopped(httpd_handle_t server); static bool has_log_clients(void); +/* HTTPD owner updates role and log generation together. Old queued logs cannot + * regain eligibility after a later subscribe on the same connection. */ +static void set_client_role(ts_ws_peer_t peer, ws_client_type_t type, ts_log_level_t level) +{ + ts_ws_peer_t current; + if (!ts_ws_peer_get(peer.server, peer.fd, ¤t) || !ts_ws_peer_equal(peer,current)) return; + for (int i=0;idata; - // 构造事件消息 - cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "power_event"); - cJSON_AddStringToObject(msg, "state", power_state_to_string(status->state)); - cJSON_AddNumberToObject(msg, "voltage", status->current_voltage); - cJSON_AddNumberToObject(msg, "countdown", status->countdown_remaining_sec); - cJSON_AddNumberToObject(msg, "protection_count", status->protection_count); - - // 根据事件 ID 添加具体事件类型(使用 ts_power_policy_event_t 枚举值) - const char *event_name = "unknown"; - switch (event->id) { - case TS_POWER_POLICY_EVENT_STATE_CHANGED: event_name = "state_changed"; break; - case TS_POWER_POLICY_EVENT_LOW_VOLTAGE: event_name = "low_voltage"; break; - case TS_POWER_POLICY_EVENT_COUNTDOWN_TICK: event_name = "countdown_tick"; break; - case TS_POWER_POLICY_EVENT_SHUTDOWN_START: event_name = "shutdown_start"; break; - case TS_POWER_POLICY_EVENT_PROTECTED: event_name = "protected"; break; - case TS_POWER_POLICY_EVENT_RECOVERY_START: event_name = "recovery_start"; break; - case TS_POWER_POLICY_EVENT_RECOVERY_COMPLETE: event_name = "recovery_complete"; break; - case TS_POWER_POLICY_EVENT_DEBUG_TICK: event_name = "debug_tick"; break; - } - cJSON_AddStringToObject(msg, "event", event_name); - - char *json = cJSON_PrintUnformatted(msg); - cJSON_Delete(msg); - - if (json) { - // 广播给所有连接的客户端 - ts_webui_broadcast(json); - free(json); - } + bool tick=event->id==TS_POWER_POLICY_EVENT_COUNTDOWN_TICK || event->id==TS_POWER_POLICY_EVENT_DEBUG_TICK; + ts_ws_reservation_t reservation; + esp_err_t ret=ts_ws_power_reserve(tick,&reservation); + if(ret!=ESP_OK) { + TS_LOGW(TAG,"Power notification admission failed: event=%ld result=%d",(long)event->id,ret); + return; /* bounded overload; never wait on protection's event callback */ + } + if(!reservation.message)return; + const char *event_name="unknown"; + switch(event->id) { + case TS_POWER_POLICY_EVENT_STATE_CHANGED:event_name="state_changed";break; + case TS_POWER_POLICY_EVENT_LOW_VOLTAGE:event_name="low_voltage";break; + case TS_POWER_POLICY_EVENT_COUNTDOWN_TICK:event_name="countdown_tick";break; + case TS_POWER_POLICY_EVENT_SHUTDOWN_START:event_name="shutdown_start";break; + case TS_POWER_POLICY_EVENT_PROTECTED:event_name="protected";break; + case TS_POWER_POLICY_EVENT_RECOVERY_START:event_name="recovery_start";break; + case TS_POWER_POLICY_EVENT_RECOVERY_COMPLETE:event_name="recovery_complete";break; + case TS_POWER_POLICY_EVENT_DEBUG_TICK:event_name="debug_tick";break; + } + /* Fixed schema, numeric values and constant strings; no heap JSON needed. + * Preserve cJSON's non-finite-number encoding as null. */ + char voltage[32],json[512]; + if(isfinite(status->current_voltage))snprintf(voltage,sizeof(voltage),"%.17g",(double)status->current_voltage); + else strcpy(voltage,"null"); + int n=snprintf(json,sizeof(json),"{\"type\":\"power_event\",\"state\":\"%s\",\"voltage\":%s,\"countdown\":%lu,\"protection_count\":%lu,\"event\":\"%s\"}", + power_state_to_string(status->state),voltage,(unsigned long)status->countdown_remaining_sec,(unsigned long)status->protection_count,event_name); + ret=n<0 || n>=(int)sizeof(json)?ESP_ERR_INVALID_SIZE:ts_ws_power_publish(&reservation,json); + ts_ws_reservation_release(&reservation); + if(ret!=ESP_OK)TS_LOGW(TAG,"Power notification submission failed: event=%ld result=%d",(long)event->id,ret); + } /*===========================================================================*/ /* SSH Shell Functions */ /*===========================================================================*/ -/* 发送 SSH 输出到 WebSocket 客户端 */ -static void ssh_send_output(const char *data, size_t len) +/* Request errors must go to the requester, never mutate an existing session. */ +static void ssh_request_error(httpd_req_t *req, const char *message) { - if (s_ssh_client_fd < 0 || !s_server || !data || len == 0) return; - - // 查找客户端 - httpd_handle_t hd = NULL; - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { - hd = s_clients[i].hd; - break; - } - } - if (!hd) return; - - // 构造消息(base64 可以处理二进制,但这里假设是文本) - cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_output"); - - // 复制数据并确保 null 结尾 (PSRAM first) - char *buf = heap_caps_malloc(len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!buf) buf = malloc(len + 1); - if (buf) { - memcpy(buf, data, len); - buf[len] = '\0'; - cJSON_AddStringToObject(msg, "data", buf); - free(buf); - } - - char *json = cJSON_PrintUnformatted(msg); - cJSON_Delete(msg); - - if (json) { - httpd_ws_frame_t ws_pkt = { - .type = HTTPD_WS_TYPE_TEXT, - .payload = (uint8_t *)json, - .len = strlen(json) - }; - httpd_ws_send_frame_async(hd, s_ssh_client_fd, &ws_pkt); - free(json); - } + TS_WS_TEST_POINT("request_error_encode"); + cJSON *msg=cJSON_CreateObject(); + bool ok=msg && cJSON_AddStringToObject(msg,"type","error") && cJSON_AddStringToObject(msg,"message",message); + char *json=ok?cJSON_PrintUnformatted(msg):NULL;cJSON_Delete(msg); + const char *text=json?json:"{\"type\":\"error\",\"message\":\"SSH request rejected\"}"; + httpd_ws_frame_t frame={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)text,.len=strlen(text)}; + esp_err_t ret=httpd_ws_send_frame(req,&frame); + if(ret!=ESP_OK)TS_LOGW(TAG,"SSH request error could not be sent: %s",esp_err_to_name(ret)); + free(json); } -/* 发送 SSH 状态消息 */ -static void ssh_send_status(const char *status, const char *message) +static void shell_resources_close(ssh_shell_context_t *ctx) { - if (s_ssh_client_fd < 0 || !s_server) return; - - httpd_handle_t hd = NULL; - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { - hd = s_clients[i].hd; - break; - } - } - if (!hd) return; - - cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_status"); - cJSON_AddStringToObject(msg, "status", status); - if (message) { - cJSON_AddStringToObject(msg, "message", message); - } - - char *json = cJSON_PrintUnformatted(msg); - cJSON_Delete(msg); - - if (json) { - httpd_ws_frame_t ws_pkt = { - .type = HTTPD_WS_TYPE_TEXT, - .payload = (uint8_t *)json, - .len = strlen(json) - }; - httpd_ws_send_frame_async(hd, s_ssh_client_fd, &ws_pkt); - free(json); - } + xSemaphoreTake(ctx->io,portMAX_DELAY); + if(ctx->shell){ts_ssh_shell_close(ctx->shell);ctx->shell=NULL;} + if(ctx->session){ts_ssh_disconnect(ctx->session);ts_ssh_session_destroy(ctx->session);ctx->session=NULL;} + xSemaphoreGive(ctx->io); } - -/* 前向声明 */ -static void ssh_cleanup(void); - -/* SSH Shell 轮询任务 */ -static void ssh_poll_task(void *arg) +static void shell_destroy(void *data) { - char buf[SSH_OUTPUT_BUF_SIZE]; - bool need_cleanup = false; - - TS_LOGD(TAG, "SSH poll task started"); - - while (s_ssh_running && s_ssh_shell) { - size_t read_len = 0; - esp_err_t ret = ts_ssh_shell_read(s_ssh_shell, buf, sizeof(buf) - 1, &read_len); - - if (ret == ESP_OK && read_len > 0) { - buf[read_len] = '\0'; - ssh_send_output(buf, read_len); - } - - // 检查 shell 是否还活跃 - if (!ts_ssh_shell_is_active(s_ssh_shell)) { - TS_LOGD(TAG, "SSH shell closed by remote"); - ssh_send_status("closed", "SSH session closed"); - need_cleanup = true; // 标记需要清理 - break; - } - - vTaskDelay(pdMS_TO_TICKS(20)); // 50Hz 轮询 - } - - TS_LOGD(TAG, "SSH poll task ended"); - s_ssh_poll_task = NULL; - - // 如果是因为远程关闭而退出,需要清理 SSH 会话 - if (need_cleanup && s_ssh_session) { - // 清理 shell(已经关闭,只需释放资源) - if (s_ssh_shell) { - ts_ssh_shell_close(s_ssh_shell); - s_ssh_shell = NULL; - } - // 清理 session - if (s_ssh_session) { - ts_ssh_disconnect(s_ssh_session); - ts_ssh_session_destroy(s_ssh_session); - s_ssh_session = NULL; - } - // 更新客户端类型 - if (s_ssh_client_fd >= 0) { - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { - s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; - break; - } - } - s_ssh_client_fd = -1; - } - TS_LOGD(TAG, "SSH session cleaned up after remote close"); - } - - vTaskDelete(NULL); + ssh_shell_context_t *ctx=data; + if(!ctx)return; + /* Network cleanup belongs to the creator/poller, never the TX worker. */ + assert(!ctx->session && !ctx->shell); + vSemaphoreDelete(ctx->io);free(ctx); } - -/* 清理 SSH 会话 */ -static void ssh_cleanup(void) +static void ssh_close(ts_ws_operation_t *op,const char *status,const char *message) { - s_ssh_running = false; - - if (s_ssh_poll_task) { - // 等待任务结束 - vTaskDelay(pdMS_TO_TICKS(100)); - } - - if (s_ssh_shell) { - ts_ssh_shell_close(s_ssh_shell); - s_ssh_shell = NULL; - } - - if (s_ssh_session) { - ts_ssh_disconnect(s_ssh_session); - ts_ssh_session_destroy(s_ssh_session); - s_ssh_session = NULL; - } - - // 更新客户端类型 - if (s_ssh_client_fd >= 0) { - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { - s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; - break; - } - } - } - s_ssh_client_fd = -1; - - TS_LOGD(TAG, "SSH session cleaned up"); + if(!ts_ws_op_close_begin(op))return; + cJSON *msg=cJSON_CreateObject(); + bool ok=msg && cJSON_AddStringToObject(msg,"type","ssh_status") && + cJSON_AddStringToObject(msg,"status",status) && cJSON_AddStringToObject(msg,"message",message); + char *json=ok?cJSON_PrintUnformatted(msg):NULL;cJSON_Delete(msg); + ts_ws_op_close_finish(op,json);free(json); } - -/* 处理 SSH Shell 连接请求 */ -static void handle_ssh_connect(httpd_req_t *req, cJSON *params) +static void ssh_send_output(ssh_shell_context_t *ctx,const char *data,size_t len) { - int fd = httpd_req_to_sockfd(req); - - // 检查是否已有 SSH 会话 - if (s_ssh_session != NULL) { - ssh_send_status("error", "Another SSH session is active"); - return; - } - - // 解析参数 - cJSON *host = cJSON_GetObjectItem(params, "host"); - cJSON *port = cJSON_GetObjectItem(params, "port"); - cJSON *user = cJSON_GetObjectItem(params, "user"); - cJSON *password = cJSON_GetObjectItem(params, "password"); - - if (!host || !cJSON_IsString(host) || !user || !cJSON_IsString(user)) { - ssh_send_status("error", "Missing host or user"); - return; - } - - int ssh_port = (port && cJSON_IsNumber(port)) ? port->valueint : 22; - const char *ssh_password = (password && cJSON_IsString(password)) ? password->valuestring : ""; - - TS_LOGD(TAG, "SSH connect: %s@%s:%d", user->valuestring, host->valuestring, ssh_port); - - // 设置 SSH 客户端 fd - s_ssh_client_fd = fd; - - // 更新客户端类型 - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == fd) { - s_clients[i].type = WS_CLIENT_TYPE_SSH_SHELL; - break; - } - } - - // 发送连接中状态 - ssh_send_status("connecting", "Connecting to SSH server..."); - - // 配置 SSH - ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); - config.host = host->valuestring; - config.port = ssh_port; - config.username = user->valuestring; - config.auth_method = TS_SSH_AUTH_PASSWORD; - config.auth.password = ssh_password; - config.timeout_ms = 10000; - - // 创建会话 - esp_err_t ret = ts_ssh_session_create(&config, &s_ssh_session); - if (ret != ESP_OK) { - ssh_send_status("error", "Failed to create SSH session"); - ssh_cleanup(); - return; - } - - // 连接 - ret = ts_ssh_connect(s_ssh_session); - if (ret != ESP_OK) { - char err_msg[128]; - snprintf(err_msg, sizeof(err_msg), "Connection failed: %s", ts_ssh_get_error(s_ssh_session)); - ssh_send_status("error", err_msg); - ssh_cleanup(); - return; - } - - // 打开 Shell - ts_shell_config_t shell_config = TS_SHELL_DEFAULT_CONFIG(); - shell_config.term_width = 80; - shell_config.term_height = 24; - shell_config.read_timeout_ms = 50; - - ret = ts_ssh_shell_open(s_ssh_session, &shell_config, &s_ssh_shell); - if (ret != ESP_OK) { - ssh_send_status("error", "Failed to open shell"); - ssh_cleanup(); - return; - } - - // 发送连接成功状态 - ssh_send_status("connected", "SSH shell ready"); - - // 启动轮询任务(栈需要足够大以容纳 libssh2 缓冲区,使用 PSRAM) - s_ssh_running = true; - xTaskCreateWithCaps(ssh_poll_task, "ssh_poll", 4096, NULL, 5, &s_ssh_poll_task, MALLOC_CAP_SPIRAM); + if(!data || !len)return; + ts_ws_output_ticket_t ticket; + if(!ts_ws_op_output_begin(ctx->op,&ticket))return; + char *buf=NULL,*json=NULL;cJSON *msg=NULL; + if(ticket.count) { + buf=heap_caps_malloc(len+1,MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + if(!buf)buf=malloc(len+1); + if(buf){memcpy(buf,data,len);buf[len]=0;msg=cJSON_CreateObject(); + if(msg && cJSON_AddStringToObject(msg,"type","ssh_output") && cJSON_AddStringToObject(msg,"data",buf))json=cJSON_PrintUnformatted(msg);} + } + free(buf);cJSON_Delete(msg);ts_ws_op_output_finish(&ticket,json);free(json); } - -/* 处理 SSH Shell 输入 */ -static void handle_ssh_input(const char *data) +/* Startup controls are synchronous on the HTTPD owner. Creator + poller refs + * pin STARTING; OPEN is published only after connected has returned successfully. + * They cannot be overtaken by ordinary output or an asynchronous close callback. */ +static esp_err_t ssh_start_status(ssh_shell_context_t *ctx,const char *status,const char *message) { - if (!s_ssh_shell || !data) return; - - size_t len = strlen(data); - if (len == 0) return; - - ts_ssh_shell_write(s_ssh_shell, data, len, NULL); + if(!ts_ws_op_starting(ctx->op))return ESP_ERR_INVALID_STATE; + cJSON *msg=cJSON_CreateObject(); + bool ok=msg && cJSON_AddStringToObject(msg,"type","ssh_status") && + cJSON_AddStringToObject(msg,"status",status) && cJSON_AddStringToObject(msg,"message",message); + char *json=ok?cJSON_PrintUnformatted(msg):NULL;cJSON_Delete(msg); + esp_err_t ret=ESP_ERR_NO_MEM; + if(json){ts_ws_peer_t peer=ts_ws_op_peer(ctx->op);httpd_ws_frame_t f={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)json,.len=strlen(json)}; + ret=ts_ws_transport_send(peer.server,peer.fd,&f);} + free(json);return ret; } - -/* 处理 SSH Shell 断开 */ -static void handle_ssh_disconnect(void) +/* Poller remains the only ordinary observation producer. User disconnect is + * handed to that producer, preserving the disconnecting/closed wire messages. */ +static void ssh_disconnecting(ssh_shell_context_t *ctx) { - if (s_ssh_session) { - ssh_send_status("disconnecting", "Closing SSH session..."); - ssh_cleanup(); - } + ts_ws_output_ticket_t ticket; + if(ts_ws_op_output_begin(ctx->op,&ticket)) + ts_ws_op_output_finish(&ticket,"{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}"); + ssh_close(ctx->op,"closed","SSH session closed"); } - -/* 处理 SSH Shell 信号 */ -static void handle_ssh_signal(const char *signal) +static void ssh_poll_task(void *arg) { - if (s_ssh_shell && signal) { - ts_ssh_shell_send_signal(s_ssh_shell, signal); - } + ssh_shell_context_t *ctx=arg;ts_ws_operation_t *op=ctx->op; + char buf[SSH_OUTPUT_BUF_SIZE]; + while(ts_ws_op_starting(op))vTaskDelay(1); + while(ts_ws_op_is_open(op)) { + if(ctx->disconnect_requested){ssh_disconnecting(ctx);break;} + size_t n=0; + xSemaphoreTake(ctx->io,portMAX_DELAY); + esp_err_t ret=ts_ssh_shell_read(ctx->shell,buf,sizeof(buf)-1,&n); + bool active=ts_ssh_shell_is_active(ctx->shell); + bool failed=ts_ssh_shell_get_state(ctx->shell)==TS_SHELL_STATE_ERROR; + xSemaphoreGive(ctx->io); + if(ret==ESP_OK && n)ssh_send_output(ctx,buf,n); + if(!active){ssh_close(op,failed?"error":"closed",failed?"SSH channel failed; remote result is not confirmed":"SSH session closed");break;} + vTaskDelay(pdMS_TO_TICKS(20)); + } + shell_resources_close(ctx); + ts_ws_op_executor_done(op); + vTaskDeleteWithCaps(NULL); } - -/* 处理 SSH Shell 窗口大小调整 */ -static void handle_ssh_resize(int width, int height) +static void ssh_cleanup(void) +{ + ts_ws_operation_t *op=ts_ws_op_shell_owner(); + if(!op)return; + ssh_close(op,"closed","SSH session closed"); + ts_ws_op_release(op); +} +static void handle_ssh_connect(httpd_req_t *req,cJSON *params) +{ + cJSON *host=cJSON_GetObjectItem(params,"host"),*user=cJSON_GetObjectItem(params,"user"); + cJSON *port=cJSON_GetObjectItem(params,"port"),*password=cJSON_GetObjectItem(params,"password"); + if(!cJSON_IsString(host) || !cJSON_IsString(user)){ssh_request_error(req,"Missing host or user");return;} + ts_ws_peer_t peer=*(ts_ws_peer_t*)req->sess_ctx; + esp_err_t admission; + ts_ws_operation_t *op=ts_ws_op_create(TS_WS_OP_SHELL,peer,&admission); + if(!op){ssh_request_error(req,admission==ESP_ERR_NO_MEM?"SSH result delivery capacity unavailable":"Another SSH session is active");return;} + ssh_shell_context_t *ctx=calloc(1,sizeof(*ctx)); + if(!ctx || !(ctx->io=xSemaphoreCreateMutex())) { + free(ctx);ts_ws_op_discard(op);ts_ws_op_executor_done(op);ssh_request_error(req,"Failed to create SSH session");return; + } + ctx->op=op;ts_ws_op_bind(op,ctx,shell_destroy); + set_client_role(peer,WS_CLIENT_TYPE_SSH_SHELL,TS_LOG_NONE); + const char *error="SSH connection status delivery failed";bool poller=false; + if(ssh_start_status(ctx,"connecting","Connecting to SSH server...")!=ESP_OK)goto failed; + ts_ssh_config_t config=TS_SSH_DEFAULT_CONFIG(); + config.host=host->valuestring;config.username=user->valuestring; + config.port=cJSON_IsNumber(port)?port->valueint:22; + config.auth_method=TS_SSH_AUTH_PASSWORD;config.auth.password=cJSON_IsString(password)?password->valuestring:"";config.timeout_ms=10000; + error="Failed to create SSH session"; + if(ts_ssh_session_create(&config,&ctx->session)!=ESP_OK)goto failed; + if(ts_ssh_connect(ctx->session)!=ESP_OK){error=ts_ssh_get_error(ctx->session);goto failed;} + ts_shell_config_t shell_config=TS_SHELL_DEFAULT_CONFIG();shell_config.term_width=80;shell_config.term_height=24;shell_config.read_timeout_ms=50; + error="Failed to open shell"; + if(ts_ssh_shell_open(ctx->session,&shell_config,&ctx->shell)!=ESP_OK)goto failed; + ts_ws_op_executor_take(op); + if(xTaskCreateWithCaps(ssh_poll_task,"ssh_poll",SSH_POLL_STACK_SIZE,ctx,5,NULL,MALLOC_CAP_SPIRAM)!=pdPASS){ts_ws_op_executor_done(op);error="Failed to create SSH session";goto failed;} + poller=true;error="SSH shell closed during startup"; + if(!ts_ssh_shell_is_active(ctx->shell))goto failed; + error="SSH readiness delivery failed"; + if(ssh_start_status(ctx,"connected","SSH shell ready")!=ESP_OK)goto failed; + ts_ws_op_open(op);ts_ws_op_executor_done(op);return; +failed: + ssh_close(op,"error",error?error:"SSH connection failed"); + if(!poller)shell_resources_close(ctx); + set_client_role(peer,WS_CLIENT_TYPE_TERMINAL,TS_LOG_NONE); + ts_ws_op_executor_done(op); +} +/* Page control has one ownership gate. The acquired original context remains + * pinned across resource I/O; no handler can retarget the current Shell. */ +static void handle_ssh_control(httpd_req_t *req,ts_ws_peer_t peer,const char *type,cJSON *msg) { - if (s_ssh_shell && width > 0 && height > 0) { - ts_ssh_shell_resize(s_ssh_shell, width, height); + ts_ws_operation_t *op=ts_ws_op_shell_control(peer); + if(!op){ssh_request_error(req,"This connection does not own an active SSH session");return;} + ssh_shell_context_t *ctx=ts_ws_op_data(op); + if(!strcmp(type,"ssh_disconnect"))ctx->disconnect_requested=true; + else { + esp_err_t ret=ESP_ERR_INVALID_ARG;bool active=false; + xSemaphoreTake(ctx->io,portMAX_DELAY); + if(ctx->shell && ts_ws_op_is_open(op)) { + active=true; + if(!strcmp(type,"ssh_input")) { + cJSON *data=cJSON_GetObjectItem(msg,"data"); + if(cJSON_IsString(data))ret=ts_ssh_shell_write(ctx->shell,data->valuestring,strlen(data->valuestring),NULL); + } else if(!strcmp(type,"ssh_signal")) { + cJSON *signal=cJSON_GetObjectItem(msg,"signal"); + if(cJSON_IsString(signal))ret=ts_ssh_shell_send_signal(ctx->shell,signal->valuestring); + } else { + cJSON *w=cJSON_GetObjectItem(msg,"width"),*h=cJSON_GetObjectItem(msg,"height"); + if(cJSON_IsNumber(w) && cJSON_IsNumber(h) && w->valuedouble>=1 && w->valuedouble<=UINT16_MAX && h->valuedouble>=1 && h->valuedouble<=UINT16_MAX && + w->valuedouble==w->valueint && h->valuedouble==h->valueint) + ret=ts_ssh_shell_resize(ctx->shell,w->valueint,h->valueint); + } + } + if(ctx->shell)active=ts_ssh_shell_is_active(ctx->shell); + xSemaphoreGive(ctx->io); + if(ret!=ESP_OK){ + if(!active)ssh_close(op,"error","SSH channel failed; remote result is not confirmed"); + else ssh_request_error(req,ret==ESP_ERR_NOT_SUPPORTED?"Unsupported SSH signal": + ret==ESP_ERR_INVALID_ARG?"Invalid SSH control parameters":"SSH control request failed; input was not replayed"); + } } + ts_ws_op_release(op); } /*===========================================================================*/ @@ -482,78 +385,24 @@ static void terminal_output_cb(const char *data, size_t len, void *user_data) } /* 前向声明 */ -static void cleanup_disconnected_client(int fd); +static void cleanup_disconnected_client(ts_ws_peer_t peer); -static void add_client(httpd_handle_t hd, int fd, ws_client_type_t type) +static esp_err_t add_client(httpd_req_t *req, ws_client_type_t type) { - // 首先检查是否已存在相同 fd 的客户端(重连情况) - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == fd) { - // 已存在,更新类型 - s_clients[i].type = type; - s_clients[i].hd = hd; - TS_LOGD(TAG, "WebSocket client reconnected (fd=%d, type=%s)", - fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "event"); - return; - } - } - - // 查找空槽位 - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (!s_clients[i].active) { - s_clients[i].active = true; - s_clients[i].fd = fd; - s_clients[i].hd = hd; - s_clients[i].type = type; - TS_LOGD(TAG, "WebSocket client connected (fd=%d, type=%s)", - fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "event"); - return; - } - } - - // 没有空槽位,尝试清理可能已断开但未标记的连接 - TS_LOGW(TAG, "No free WebSocket slots, attempting to clean up stale connections..."); - int oldest_event_slot = -1; - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active) { - // 检查 socket 状态(使用 recv 探测,MSG_PEEK | MSG_DONTWAIT) - char probe; - int result = recv(s_clients[i].fd, &probe, 1, MSG_PEEK | MSG_DONTWAIT); - if (result == 0 || (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) { - // Socket 已关闭或错误 - int old_fd = s_clients[i].fd; - TS_LOGI(TAG, "Cleaned up stale connection (fd=%d, recv=%d, errno=%d)", old_fd, result, errno); - cleanup_disconnected_client(old_fd); - // cleanup_disconnected_client 已经设置 active=false,现在可以使用这个槽位 - s_clients[i].active = true; - s_clients[i].fd = fd; - s_clients[i].hd = hd; - s_clients[i].type = type; - TS_LOGD(TAG, "WebSocket client connected after cleanup (fd=%d, type=%s)", - fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "event"); - return; - } - // 记录最旧的普通事件客户端槽位(非终端/SSH) - if (s_clients[i].type == WS_CLIENT_TYPE_EVENT && oldest_event_slot < 0) { - oldest_event_slot = i; - } - } - } - - // 如果所有连接都活跃,且新连接是终端/SSH,抢占最旧的事件客户端 - if ((type == WS_CLIENT_TYPE_TERMINAL || type == WS_CLIENT_TYPE_SSH_SHELL) && oldest_event_slot >= 0) { - int evicted_fd = s_clients[oldest_event_slot].fd; - TS_LOGW(TAG, "All slots full, evicting oldest event client (fd=%d) for %s", - evicted_fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "ssh"); - cleanup_disconnected_client(evicted_fd); - s_clients[oldest_event_slot].active = true; - s_clients[oldest_event_slot].fd = fd; - s_clients[oldest_event_slot].hd = hd; - s_clients[oldest_event_slot].type = type; - return; + ts_ws_peer_t peer; + esp_err_t ret = ts_ws_peer_open(req, &peer); + if (ret != ESP_OK) return ret; + for (int i = 0; i < MAX_WS_CLIENTS; ++i) if (!s_clients[i].active) { + s_clients[i].peer = peer; + s_clients[i].fd = peer.fd; + s_clients[i].hd = peer.server; + s_clients[i].type = type; + s_clients[i].log_min_level = TS_LOG_NONE; + s_clients[i].active = true; + return ESP_OK; } - - TS_LOGE(TAG, "All WebSocket slots are occupied by active connections"); + ts_ws_peer_close(peer); + return ESP_ERR_NO_MEM; } /* 处理终端命令执行 */ @@ -581,7 +430,7 @@ static void handle_terminal_command(httpd_req_t *req, const char *command) return; } - TS_LOGD(TAG, "Terminal exec: %s", command); + TS_LOGD(TAG, "Terminal exec (%u bytes)", (unsigned)strlen(command)); // 清空输出缓冲区 if (s_output_mutex && xSemaphoreTake(s_output_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { @@ -649,10 +498,12 @@ static void start_terminal_session(httpd_req_t *req) // 检查旧的终端 fd 是否还在活跃客户端列表中 bool old_fd_active = false; httpd_handle_t old_hd = NULL; + ts_ws_peer_t old_peer={0}; for (int i = 0; i < MAX_WS_CLIENTS; i++) { if (s_clients[i].active && s_clients[i].fd == s_terminal_client_fd) { old_fd_active = true; old_hd = s_clients[i].hd; + old_peer=s_clients[i].peer; break; } } @@ -682,12 +533,12 @@ static void start_terminal_session(httpd_req_t *req) .payload = (uint8_t *)close_json, .len = strlen(close_json) }; - httpd_ws_send_frame_async(old_hd, s_terminal_client_fd, &ws_pkt); + ts_ws_transport_send(old_hd, s_terminal_client_fd, &ws_pkt); free(close_json); } // 清理旧会话 - cleanup_disconnected_client(s_terminal_client_fd); + cleanup_disconnected_client(old_peer); s_terminal_client_fd = -1; // 短暂延迟确保关闭消息发送 @@ -698,7 +549,7 @@ static void start_terminal_session(httpd_req_t *req) // 设置为终端客户端 for (int i = 0; i < MAX_WS_CLIENTS; i++) { if (s_clients[i].active && s_clients[i].fd == fd) { - s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; + set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_TERMINAL, TS_LOG_NONE); break; } } @@ -729,15 +580,18 @@ static void start_terminal_session(httpd_req_t *req) } /* 清理断开的客户端 */ -static void cleanup_disconnected_client(int fd) +static void cleanup_disconnected_client(ts_ws_peer_t peer) { bool was_log_client = false; - - // 清理订阅(新增) - ts_ws_client_disconnected(fd); - + int fd=peer.fd; + ts_ws_peer_t live; + if(ts_ws_peer_get(peer.server,peer.fd,&live) && ts_ws_peer_equal(live,peer)) { + ts_ws_peer_close(peer); + return; + } + for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].fd == fd) { + if (s_clients[i].active && ts_ws_peer_equal(s_clients[i].peer,peer)) { // 如果是终端客户端,清理输出回调 if (s_clients[i].type == WS_CLIENT_TYPE_TERMINAL && s_terminal_client_fd == fd) { ts_console_clear_output_cb(); @@ -746,10 +600,6 @@ static void cleanup_disconnected_client(int fd) xSemaphoreGive(s_terminal_mutex); } } - // 如果是 SSH Shell 客户端,清理 SSH 会话 - if (s_clients[i].type == WS_CLIENT_TYPE_SSH_SHELL && s_ssh_client_fd == fd) { - ssh_cleanup(); - } // 检查是否是日志客户端 if (s_clients[i].type == WS_CLIENT_TYPE_LOG) { was_log_client = true; @@ -766,15 +616,27 @@ static void cleanup_disconnected_client(int fd) } } +static void peer_closed(ts_ws_peer_t peer) +{ + ts_ws_client_disconnected(peer); + ts_ws_operation_t *op=ts_ws_op_shell_connection(peer); + if(op){ssh_close(op,"closed","SSH session closed");ts_ws_op_release(op);} + cleanup_disconnected_client(peer); +} + static esp_err_t ws_handler(httpd_req_t *req) { if (req->method == HTTP_GET) { TS_LOGD(TAG, "WebSocket handshake"); // 初次连接时添加为事件客户端 - add_client(req->handle, httpd_req_to_sockfd(req), WS_CLIENT_TYPE_EVENT); - return ESP_OK; + if (s_ws_stopping) return ESP_ERR_INVALID_STATE; + return add_client(req, WS_CLIENT_TYPE_EVENT); } + ts_ws_peer_t peer; + if (!req->sess_ctx || !ts_ws_peer_get(req->handle, httpd_req_to_sockfd(req), &peer) || + !ts_ws_peer_equal(peer, *(ts_ws_peer_t *)req->sess_ctx)) return ESP_ERR_INVALID_STATE; + httpd_ws_frame_t ws_pkt; memset(&ws_pkt, 0, sizeof(ws_pkt)); ws_pkt.type = HTTPD_WS_TYPE_TEXT; @@ -783,14 +645,14 @@ static esp_err_t ws_handler(httpd_req_t *req) esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0); if (ret != ESP_OK) { TS_LOGD(TAG, "ws_recv_frame error: %s", esp_err_to_name(ret)); - cleanup_disconnected_client(httpd_req_to_sockfd(req)); + cleanup_disconnected_client(peer); return ret; } // 处理关闭帧 if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) { TS_LOGD(TAG, "WebSocket close frame received"); - cleanup_disconnected_client(httpd_req_to_sockfd(req)); + cleanup_disconnected_client(peer); return ESP_OK; } @@ -810,6 +672,7 @@ static esp_err_t ws_handler(httpd_req_t *req) ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len); if (ret != ESP_OK) { + cleanup_disconnected_client(peer); free(buf); return ret; } @@ -824,6 +687,17 @@ static esp_err_t ws_handler(httpd_req_t *req) if (msg) { cJSON *type = cJSON_GetObjectItem(msg, "type"); if (type && cJSON_IsString(type)) { + /* Keep existing connections (and heartbeat) alive while results drain. + * Reject new work with a protocol error, not an HTTPD session error. */ + if(s_ws_stopping && strcmp(type->valuestring,"ping") && + strcmp(type->valuestring,"unsubscribe")) { + const char *error="{\"type\":\"error\",\"message\":\"Service is stopping\"}"; + httpd_ws_frame_t frame={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)error,.len=strlen(error)}; + esp_err_t result=httpd_ws_send_frame(req,&frame); + cJSON_Delete(msg); + return result; + } + TS_LOGD(TAG, "WS msg type=%s from fd=%d", type->valuestring, httpd_req_to_sockfd(req)); if (strcmp(type->valuestring, "ping") == 0) { @@ -840,12 +714,11 @@ static esp_err_t ws_handler(httpd_req_t *req) } else if (strcmp(type->valuestring, "subscribe") == 0) { // 处理订阅请求(新增:topic 订阅) - int fd = httpd_req_to_sockfd(req); cJSON *topic = cJSON_GetObjectItem(msg, "topic"); cJSON *params = cJSON_GetObjectItem(msg, "params"); if (topic && cJSON_IsString(topic)) { - esp_err_t ret = ts_ws_subscribe(fd, topic->valuestring, params); + esp_err_t ret = ts_ws_subscribe(*(ts_ws_peer_t *)req->sess_ctx, topic->valuestring, params); // 发送确认消息 cJSON *ack = cJSON_CreateObject(); @@ -871,11 +744,10 @@ static esp_err_t ws_handler(httpd_req_t *req) } else if (strcmp(type->valuestring, "unsubscribe") == 0) { // 处理取消订阅请求(新增) - int fd = httpd_req_to_sockfd(req); cJSON *topic = cJSON_GetObjectItem(msg, "topic"); if (topic && cJSON_IsString(topic)) { - esp_err_t ret = ts_ws_unsubscribe(fd, topic->valuestring); + esp_err_t ret = ts_ws_unsubscribe(*(ts_ws_peer_t *)req->sess_ctx, topic->valuestring); // 发送确认消息 cJSON *ack = cJSON_CreateObject(); @@ -918,7 +790,7 @@ static esp_err_t ws_handler(httpd_req_t *req) // 恢复为普通事件客户端 for (int i = 0; i < MAX_WS_CLIENTS; i++) { if (s_clients[i].active && s_clients[i].fd == fd) { - s_clients[i].type = WS_CLIENT_TYPE_EVENT; + set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_EVENT, TS_LOG_NONE); break; } } @@ -930,31 +802,9 @@ static esp_err_t ws_handler(httpd_req_t *req) // SSH 连接请求 handle_ssh_connect(req, msg); } - else if (strcmp(type->valuestring, "ssh_input") == 0) { - // SSH 输入 - cJSON *data = cJSON_GetObjectItem(msg, "data"); - if (data && cJSON_IsString(data)) { - handle_ssh_input(data->valuestring); - } - } - else if (strcmp(type->valuestring, "ssh_disconnect") == 0) { - // SSH 断开 - handle_ssh_disconnect(); - } - else if (strcmp(type->valuestring, "ssh_signal") == 0) { - // SSH 信号 (如 INT, TERM) - cJSON *sig = cJSON_GetObjectItem(msg, "signal"); - if (sig && cJSON_IsString(sig)) { - handle_ssh_signal(sig->valuestring); - } - } - else if (strcmp(type->valuestring, "ssh_resize") == 0) { - // SSH 窗口大小调整 - cJSON *width = cJSON_GetObjectItem(msg, "width"); - cJSON *height = cJSON_GetObjectItem(msg, "height"); - if (width && height && cJSON_IsNumber(width) && cJSON_IsNumber(height)) { - handle_ssh_resize(width->valueint, height->valueint); - } + else if (!strcmp(type->valuestring,"ssh_input") || !strcmp(type->valuestring,"ssh_disconnect") || + !strcmp(type->valuestring,"ssh_signal") || !strcmp(type->valuestring,"ssh_resize")) { + handle_ssh_control(req,peer,type->valuestring,msg); } /* 日志流订阅 */ else if (strcmp(type->valuestring, "log_subscribe") == 0) { @@ -969,8 +819,7 @@ static esp_err_t ws_handler(httpd_req_t *req) bool client_found = false; for (int i = 0; i < MAX_WS_CLIENTS; i++) { if (s_clients[i].active && s_clients[i].fd == fd) { - s_clients[i].type = WS_CLIENT_TYPE_LOG; - s_clients[i].log_min_level = min_level; + set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_LOG, min_level); client_found = true; TS_LOGI(TAG, "Client %d subscribed to logs (minLevel=%d)", i, min_level); break; @@ -1002,7 +851,7 @@ static esp_err_t ws_handler(httpd_req_t *req) int fd = httpd_req_to_sockfd(req); for (int i = 0; i < MAX_WS_CLIENTS; i++) { if (s_clients[i].active && s_clients[i].fd == fd) { - s_clients[i].type = WS_CLIENT_TYPE_EVENT; + set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_EVENT, TS_LOG_NONE); break; } } @@ -1017,7 +866,7 @@ static esp_err_t ws_handler(httpd_req_t *req) for (int i = 0; i < MAX_WS_CLIENTS; i++) { if (s_clients[i].active && s_clients[i].fd == fd && s_clients[i].type == WS_CLIENT_TYPE_LOG) { - s_clients[i].log_min_level = (ts_log_level_t)level->valueint; + set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_LOG, (ts_log_level_t)level->valueint); break; } } @@ -1089,6 +938,14 @@ esp_err_t ts_webui_ws_init(void) { TS_LOGI(TAG, "Initializing WebSocket with Terminal support"); + httpd_handle_t server = ts_http_server_get_handle(); + if (!server) return ESP_ERR_INVALID_STATE; + if (s_server) return s_ws_stopping ? ESP_ERR_INVALID_STATE : ESP_OK; + esp_err_t transport_ret = ts_ws_transport_start(server, peer_closed); + if (transport_ret != ESP_OK) return transport_ret; + s_server = server; + s_ws_stopping = false; + ts_http_server_set_stop_hooks(ts_webui_ws_stop, ts_webui_ws_stopped); memset(s_clients, 0, sizeof(s_clients)); s_terminal_client_fd = -1; @@ -1109,6 +966,8 @@ esp_err_t ts_webui_ws_init(void) s_output_mutex = xSemaphoreCreateMutex(); } + if (!s_terminal_mutex || !s_output_mutex) return ESP_ERR_NO_MEM; + // 分配终端输出缓冲区(优先使用 PSRAM) if (!s_terminal_output_buf) { s_terminal_output_buf = heap_caps_malloc(TERMINAL_OUTPUT_BUF_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); @@ -1128,7 +987,6 @@ esp_err_t ts_webui_ws_init(void) } // Get HTTP server handle - httpd_handle_t server = ts_http_server_get_handle(); if (!server) { TS_LOGE(TAG, "HTTP server not started"); return ESP_ERR_INVALID_STATE; @@ -1160,13 +1018,58 @@ esp_err_t ts_webui_ws_init(void) TS_LOGI(TAG, "Power policy event handler registered"); } else { TS_LOGW(TAG, "Failed to register power event handler: %s", esp_err_to_name(ret)); + return ret; } } + ts_ws_op_enable(); TS_LOGI(TAG, "WebSocket handler registered at /ws"); return ESP_OK; } +esp_err_t ts_webui_ws_stop(httpd_handle_t server) +{ + if (ts_ws_transport_in_context() || ts_event_in_callback() || ts_ws_subscriptions_in_context()) return ESP_ERR_INVALID_STATE; + ts_ws_op_stop_admission(); + exec_retry_timer_drain(); + s_ws_stopping = true; + esp_err_t ret = ts_ws_subscriptions_pause(); + if (ret != ESP_OK) return ret; + ret = ts_ws_transport_quiesce(server, 6000); + if (ret != ESP_OK) return ret; + /* The worker still sends results even when this attempt returns busy. */ + ssh_cleanup(); + ts_ws_operation_t *exec=ts_ws_op_acquire(TS_WS_OP_EXEC,0); + bool executing=exec && ts_ws_op_executing(exec); + if(exec)ts_ws_op_release(exec); + if(executing)return ESP_ERR_INVALID_STATE; /* never cancel the remote job to stop WebUI */ + int64_t deadline=esp_timer_get_time()+2000000; + while(ts_ws_op_busy()) { + if(esp_timer_get_time()>=deadline)return ESP_ERR_TIMEOUT; + vTaskDelay(1); /* producer, callbacks, timer daemon and sender remain alive */ + } + if (s_power_event_handle) { + ret = ts_event_unregister_sync(s_power_event_handle, 6000); + if (ret != ESP_OK && ret != ESP_ERR_NOT_FOUND) return ret; + s_power_event_handle = NULL; + } + ret = ts_webui_log_stream_enable(false); + if (ret != ESP_OK) return ret; + ret = ts_ws_subscriptions_drain(); + if (ret != ESP_OK) return ret; + if(ts_ws_op_busy())return ESP_ERR_INVALID_STATE; + ret = ts_ws_transport_stop(server, 6000); + if (ret != ESP_OK) return ret; + return ts_ws_subscriptions_deinit(); +} + +void ts_webui_ws_stopped(httpd_handle_t server) +{ + ts_ws_transport_stopped(server); + if (s_server == server) s_server = NULL; + /* Existing terminal buffer/mutex are stable reusable singleton resources. */ +} + esp_err_t ts_webui_broadcast(const char *message) { if (!message) return ESP_ERR_INVALID_ARG; @@ -1177,23 +1080,7 @@ esp_err_t ts_webui_broadcast(const char *message) .len = strlen(message) }; - int sent = 0; - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active) { - esp_err_t ret = httpd_ws_send_frame_async(s_clients[i].hd, s_clients[i].fd, &ws_pkt); - if (ret == ESP_OK) { - sent++; - } else { - // Client probably disconnected - cleanup resources - int fd = s_clients[i].fd; - TS_LOGW(TAG, "Client fd=%d send failed, cleaning up", fd); - cleanup_disconnected_client(fd); - } - } - } - - TS_LOGD(TAG, "Broadcast to %d clients", sent); - return ESP_OK; + return ts_ws_transport_broadcast(&ws_pkt); } esp_err_t ts_webui_broadcast_event(const char *event_type, const char *data) @@ -1265,23 +1152,8 @@ static void log_ws_callback(const ts_log_entry_t *entry, void *user_data) .len = strlen(json) }; - // 发送给所有日志订阅客户端(根据级别过滤) - int sent_count = 0; - for (int i = 0; i < MAX_WS_CLIENTS; i++) { - if (s_clients[i].active && s_clients[i].type == WS_CLIENT_TYPE_LOG) { - // 检查级别过滤 - if (entry->level <= s_clients[i].log_min_level) { - httpd_ws_send_frame_async(s_clients[i].hd, s_clients[i].fd, &ws_pkt); - sent_count++; - } - } - } - - // Debug: Log if no clients received the message - if (sent_count == 0) { - TS_LOGD(TAG, "log_ws_callback: No clients received log (level=%d)", entry->level); - } - + ts_ws_transport_log(&ws_pkt, entry->level); + free(json); } @@ -1290,21 +1162,20 @@ static void log_ws_callback(const ts_log_entry_t *entry, void *user_data) */ esp_err_t ts_webui_log_stream_enable(bool enable) { - if (enable && !s_log_callback_handle) { - // 注册日志回调 (min_level=TS_LOG_VERBOSE, 接收所有级别) - esp_err_t ret = ts_log_add_callback(log_ws_callback, TS_LOG_VERBOSE, NULL, &s_log_callback_handle); - if (ret != ESP_OK) { - TS_LOGE(TAG, "Failed to register log callback: %s", esp_err_to_name(ret)); - return ret; + if(enable) { + if(!s_log_callback_handle) { + esp_err_t ret=ts_log_add_callback(log_ws_callback,TS_LOG_VERBOSE,NULL,&s_log_callback_handle); + if(ret!=ESP_OK)return ret; + } + /* A failed remove retains the handle; resubscribe reuses it. */ + s_log_streaming_enabled=true; + } else { + s_log_streaming_enabled=false; + if(s_log_callback_handle) { + esp_err_t ret=ts_log_remove_callback(s_log_callback_handle); + if(ret!=ESP_OK)return ret; + s_log_callback_handle=NULL; } - s_log_streaming_enabled = true; - TS_LOGI(TAG, "Log streaming enabled (receiving all levels)"); - } else if (!enable && s_log_callback_handle) { - // 移除日志回调 - s_log_streaming_enabled = false; - ts_log_remove_callback(s_log_callback_handle); - s_log_callback_handle = NULL; - TS_LOGI(TAG, "Log streaming disabled"); } return ESP_OK; } @@ -1341,6 +1212,15 @@ static void update_log_stream_state(void) /* SSH Exec 任务参数 */ typedef struct { + ts_ws_operation_t *op; + ts_ssh_session_t session; + SemaphoreHandle_t io; + TimerHandle_t timer; + atomic_bool timer_closing; + atomic_uint timer_phase; /* 0 none, 1 live, 2 delete, 3 barrier, 4 queued, 5 drained */ + atomic_uint timer_retries; + int64_t timer_retry_at; /* maintenance worker owns pacing */ + char *password_owned; ts_ssh_config_t config; char command[512]; uint32_t session_id; @@ -1365,9 +1245,6 @@ typedef struct { char *extracted_value; /* 提取的值 */ } ssh_exec_task_params_t; -/* 全局任务参数指针(用于回调访问) */ -static ssh_exec_task_params_t *s_exec_params = NULL; - /* 简单的正则表达式匹配(支持基本模式)*/ static bool simple_pattern_match(const char *text, const char *pattern, char **extracted) { @@ -1445,60 +1322,62 @@ static bool simple_pattern_match(const char *text, const char *pattern, char **e } } +static void exec_abort(ssh_exec_task_params_t *params) +{ + xSemaphoreTake(params->io,portMAX_DELAY); + if(params->session)ts_ssh_abort(params->session); + xSemaphoreGive(params->io); +} /* SSH Exec 输出回调 - 广播到所有 WebSocket 客户端并收集输出 */ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stderr, void *user_data) { if (!data || len == 0) return; - uint32_t session_id = (uint32_t)(uintptr_t)user_data; + ssh_exec_task_params_t *params=user_data; + ts_ws_op_retain(params->op); /* synchronous SSH callback borrows executor-owned params */ + uint32_t session_id=params->session_id; /* 收集输出到缓冲区 */ - if (s_exec_params && s_exec_params->collect_output && s_exec_params->output_buffer) { - size_t space = s_exec_params->output_capacity - s_exec_params->output_len - 1; + if (params && params->collect_output && params->output_buffer) { + size_t space = params->output_capacity - params->output_len - 1; size_t copy_len = (len < space) ? len : space; if (copy_len > 0) { - memcpy(s_exec_params->output_buffer + s_exec_params->output_len, data, copy_len); - s_exec_params->output_len += copy_len; - s_exec_params->output_buffer[s_exec_params->output_len] = '\0'; + memcpy(params->output_buffer + params->output_len, data, copy_len); + params->output_len += copy_len; + params->output_buffer[params->output_len] = '\0'; } } - /* 构造消息 */ - cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_exec_output"); - cJSON_AddNumberToObject(msg, "session_id", session_id); - cJSON_AddBoolToObject(msg, "is_stderr", is_stderr); - - /* 复制数据并确保 null 结尾 */ - char *buf = heap_caps_malloc(len + 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!buf) buf = malloc(len + 1); - if (buf) { - memcpy(buf, data, len); - buf[len] = '\0'; - cJSON_AddStringToObject(msg, "data", buf); - free(buf); - } - - char *json = cJSON_PrintUnformatted(msg); - cJSON_Delete(msg); - - if (json) { - ts_webui_broadcast(json); - free(json); + ts_ws_output_ticket_t ticket; + if(ts_ws_op_output_begin(params->op,&ticket)) { + if(ticket.count) { + cJSON *msg=cJSON_CreateObject(); + char *buf=heap_caps_malloc(len+1,MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + if(!buf)buf=malloc(len+1); + if(buf){memcpy(buf,data,len);buf[len]=0;} + bool encoded=buf && msg && cJSON_AddStringToObject(msg,"type","ssh_exec_output") && + cJSON_AddNumberToObject(msg,"session_id",session_id) && cJSON_AddBoolToObject(msg,"is_stderr",is_stderr) && + cJSON_AddStringToObject(msg,"data",buf); + char *json=encoded?cJSON_PrintUnformatted(msg):NULL; + free(buf);cJSON_Delete(msg); + ts_ws_op_output_finish(&ticket,json); + free(json); + + } else ts_ws_op_output_finish(&ticket,NULL); } - + /* 实时模式匹配 */ - if (s_exec_params && s_exec_params->output_buffer) { - const char *output = s_exec_params->output_buffer; + if (params && params->output_buffer) { + const char *output = params->output_buffer; bool should_send_match = false; bool pattern_matched = false; /* expect/fail 模式是否匹配 */ bool is_first_extract = false; /* 是否为首次提取 */ /* 检查失败模式(仅在尚未匹配时) */ - if (!s_exec_params->match_found && s_exec_params->fail_pattern && s_exec_params->fail_pattern[0]) { - if (simple_pattern_match(output, s_exec_params->fail_pattern, NULL)) { - s_exec_params->fail_matched = true; - s_exec_params->match_found = true; + if (!params->match_found && params->fail_pattern && params->fail_pattern[0]) { + if (simple_pattern_match(output, params->fail_pattern, NULL)) { + params->fail_matched = true; + params->match_found = true; should_send_match = true; pattern_matched = true; TS_LOGW(TAG, "Realtime fail pattern matched"); @@ -1506,11 +1385,11 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder } /* 检查期望模式(仅在尚未匹配时,且失败模式没有匹配) */ - if (!s_exec_params->match_found && !s_exec_params->fail_matched && - s_exec_params->expect_pattern && s_exec_params->expect_pattern[0]) { - if (simple_pattern_match(output, s_exec_params->expect_pattern, NULL)) { - s_exec_params->expect_matched = true; - s_exec_params->match_found = true; + if (!params->match_found && !params->fail_matched && + params->expect_pattern && params->expect_pattern[0]) { + if (simple_pattern_match(output, params->expect_pattern, NULL)) { + params->expect_matched = true; + params->match_found = true; should_send_match = true; pattern_matched = true; TS_LOGI(TAG, "Realtime expect pattern matched"); @@ -1518,11 +1397,11 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder } /* 提取值 */ - if (s_exec_params->extract_pattern && s_exec_params->extract_pattern[0]) { + if (params->extract_pattern && params->extract_pattern[0]) { char *extracted = NULL; - if (simple_pattern_match(output, s_exec_params->extract_pattern, &extracted)) { + if (simple_pattern_match(output, params->extract_pattern, &extracted)) { /* 检查是否为首次提取 */ - if (!s_exec_params->extracted_value) { + if (!params->extracted_value) { is_first_extract = true; } @@ -1530,16 +1409,16 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder bool is_new_value = false; if (is_first_extract) { is_new_value = true; - } else if (extracted && strcmp(extracted, s_exec_params->extracted_value) != 0) { + } else if (extracted && strcmp(extracted, params->extracted_value) != 0) { is_new_value = true; } if (is_new_value) { /* 释放旧值,保存新值 */ - if (s_exec_params->extracted_value) { - free(s_exec_params->extracted_value); + if (params->extracted_value) { + free(params->extracted_value); } - s_exec_params->extracted_value = extracted; + params->extracted_value = extracted; should_send_match = true; TS_LOGI(TAG, "Realtime extract: %s (first=%d)", extracted ? extracted : "(null)", is_first_extract); } else { @@ -1551,7 +1430,7 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder /* 判断是否应该停止 */ bool should_stop = false; - if (s_exec_params->stop_on_match) { + if (params->stop_on_match) { /* 勾选了"匹配后停止":expect/fail 匹配 或 首次提取成功 都应该停止 */ if (pattern_matched || is_first_extract) { should_stop = true; @@ -1560,24 +1439,28 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder /* 发送实时匹配消息 */ if (should_send_match) { + ts_ws_output_ticket_t match_ticket; + if(ts_ws_op_output_begin(params->op,&match_ticket)) { + if(match_ticket.count) { cJSON *match_msg = cJSON_CreateObject(); - cJSON_AddStringToObject(match_msg, "type", "ssh_exec_match"); - cJSON_AddNumberToObject(match_msg, "session_id", session_id); - cJSON_AddBoolToObject(match_msg, "expect_matched", s_exec_params->expect_matched); - cJSON_AddBoolToObject(match_msg, "fail_matched", s_exec_params->fail_matched); - if (s_exec_params->extracted_value) { - cJSON_AddStringToObject(match_msg, "extracted", s_exec_params->extracted_value); + bool match_encoded=match_msg!=NULL; + match_encoded = (cJSON_AddStringToObject(match_msg, "type", "ssh_exec_match"))!=NULL && match_encoded; + match_encoded = (cJSON_AddNumberToObject(match_msg, "session_id", session_id))!=NULL && match_encoded; + match_encoded = (cJSON_AddBoolToObject(match_msg, "expect_matched", params->expect_matched))!=NULL && match_encoded; + match_encoded = (cJSON_AddBoolToObject(match_msg, "fail_matched", params->fail_matched))!=NULL && match_encoded; + if (params->extracted_value) { + match_encoded = (cJSON_AddStringToObject(match_msg, "extracted", params->extracted_value))!=NULL && match_encoded; } /* 标记是否为终止匹配 */ - cJSON_AddBoolToObject(match_msg, "is_final", should_stop); + match_encoded = (cJSON_AddBoolToObject(match_msg, "is_final", should_stop))!=NULL && match_encoded; - char *match_json = cJSON_PrintUnformatted(match_msg); + char *match_json = match_encoded?cJSON_PrintUnformatted(match_msg):NULL; cJSON_Delete(match_msg); - if (match_json) { - ts_webui_broadcast(match_json); - free(match_json); - } + ts_ws_op_output_finish(&match_ticket,match_json); + free(match_json); + } else ts_ws_op_output_finish(&match_ticket,NULL); + } /* ========== 根据命令类型决定变量更新时机 ========== */ /* * 持续监控型:只有 extract_pattern,无 expect/fail/stop_on_match @@ -1586,58 +1469,58 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder * 结果导向型:有 expect/fail 或 stop_on_match * → 等命令结束时才更新变量(在 ssh_exec_task 完成处理) */ - bool is_continuous_mode = s_exec_params->extract_pattern && - !s_exec_params->expect_pattern && - !s_exec_params->fail_pattern && - !s_exec_params->stop_on_match; + bool is_continuous_mode = params->extract_pattern && + !params->expect_pattern && + !params->fail_pattern && + !params->stop_on_match; TS_LOGI(TAG, "Variable update check: var_name='%s', continuous=%d, extract=%p, expect=%p, fail=%p, stop=%d", - s_exec_params->var_name, + params->var_name, is_continuous_mode, - s_exec_params->extract_pattern, - s_exec_params->expect_pattern, - s_exec_params->fail_pattern, - s_exec_params->stop_on_match); + params->extract_pattern, + params->expect_pattern, + params->fail_pattern, + params->stop_on_match); - if (is_continuous_mode && s_exec_params->var_name[0]) { + if (is_continuous_mode && params->var_name[0]) { /* 持续监控模式:实时更新变量 */ char full_var_name[96]; ts_auto_variable_t var = {0}; - strncpy(var.source_id, s_exec_params->var_name, sizeof(var.source_id) - 1); + strncpy(var.source_id, params->var_name, sizeof(var.source_id) - 1); var.flags = 0; /* 更新 extracted 变量 */ - if (s_exec_params->extracted_value) { - snprintf(full_var_name, sizeof(full_var_name), "%s.extracted", s_exec_params->var_name); + if (params->extracted_value) { + snprintf(full_var_name, sizeof(full_var_name), "%s.extracted", params->var_name); strncpy(var.name, full_var_name, sizeof(var.name) - 1); var.value.type = TS_AUTO_VAL_STRING; - strncpy(var.value.str_val, s_exec_params->extracted_value, sizeof(var.value.str_val) - 1); + strncpy(var.value.str_val, params->extracted_value, sizeof(var.value.str_val) - 1); esp_err_t ret = ts_variable_upsert(&var); - TS_LOGI(TAG, "Registered %s = %s (ret=%d)", full_var_name, s_exec_params->extracted_value, ret); + TS_LOGI(TAG, "Registered %s = %s (ret=%d)", full_var_name, params->extracted_value, ret); } /* 更新 status 为 running */ - snprintf(full_var_name, sizeof(full_var_name), "%s.status", s_exec_params->var_name); + snprintf(full_var_name, sizeof(full_var_name), "%s.status", params->var_name); strncpy(var.name, full_var_name, sizeof(var.name) - 1); var.value.type = TS_AUTO_VAL_STRING; strncpy(var.value.str_val, "running", sizeof(var.value.str_val) - 1); ts_variable_upsert(&var); /* 更新 host */ - snprintf(full_var_name, sizeof(full_var_name), "%s.host", s_exec_params->var_name); + snprintf(full_var_name, sizeof(full_var_name), "%s.host", params->var_name); strncpy(var.name, full_var_name, sizeof(var.name) - 1); var.value.type = TS_AUTO_VAL_STRING; - strncpy(var.value.str_val, s_exec_params->config.host ? s_exec_params->config.host : "", sizeof(var.value.str_val) - 1); + strncpy(var.value.str_val, params->config.host ? params->config.host : "", sizeof(var.value.str_val) - 1); ts_variable_upsert(&var); /* 更新 timestamp */ - snprintf(full_var_name, sizeof(full_var_name), "%s.timestamp", s_exec_params->var_name); + snprintf(full_var_name, sizeof(full_var_name), "%s.timestamp", params->var_name); strncpy(var.name, full_var_name, sizeof(var.name) - 1); var.value.type = TS_AUTO_VAL_INT; var.value.int_val = (int32_t)(esp_timer_get_time() / 1000000); ts_variable_upsert(&var); - TS_LOGD(TAG, "Continuous mode: realtime update %s", s_exec_params->var_name); + TS_LOGD(TAG, "Continuous mode: realtime update %s", params->var_name); } /* 结果导向模式:变量在命令完成时更新(见下方 ssh_exec_task 完成处理) */ @@ -1645,23 +1528,72 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder if (should_stop) { TS_LOGI(TAG, "Aborting SSH execution (pattern=%d, first_extract=%d)", pattern_matched, is_first_extract); - s_exec_cancel_requested = true; - if (s_exec_session) { - ts_ssh_abort(s_exec_session); /* 直接中断 SSH 执行 */ - } + if(ts_ws_op_request_stop(params->op,OP_STOP_MATCH))exec_abort(params); } } } + ts_ws_op_release(params->op); } -/* SSH Exec 超时回调 */ -static void ssh_exec_timeout_callback(TimerHandle_t xTimer) +/* Timer's original context is pinned from creation through the daemon barrier. + * The existing WS worker retries queue admission; it never waits on the daemon. */ +static void ssh_exec_timeout_callback(TimerHandle_t timer) { - TS_LOGW(TAG, "SSH exec timeout triggered"); - s_exec_cancel_requested = true; - if (s_exec_session) { - ts_ssh_abort(s_exec_session); + ssh_exec_task_params_t *params=pvTimerGetTimerID(timer); + xSemaphoreTake(params->io,portMAX_DELAY); + if(!params->timer_closing) { + if(ts_ws_op_request_stop(params->op,OP_STOP_TIMEOUT) && params->session)ts_ssh_abort(params->session); } + xSemaphoreGive(params->io); +} +static void exec_timer_drained(void *arg,uint32_t unused) +{ + (void)unused;ssh_exec_task_params_t *params=arg; + params->timer_phase=5; + ts_ws_op_release(params->op); +} +static bool exec_maintenance(void *data) +{ + ssh_exec_task_params_t *params=data;unsigned phase=params->timer_phase; + if(phase<2 || phase>=5)return false; + if(phase==4)return true; + if(esp_timer_get_time()timer_retry_at)return true; + BaseType_t ret=pdFAIL; + if(phase==2) { + ret=xTimerDelete(params->timer,0); + if(ret==pdPASS){params->timer=NULL;params->timer_phase=3;} + } else { + params->timer_phase=4; /* callback can finish before submit returns */ + ret=xTimerPendFunctionCall(exec_timer_drained,params,0,0); + if(ret!=pdPASS)params->timer_phase=3; + } + if(ret!=pdPASS)params->timer_retry_at=esp_timer_get_time()+100000; + if(ret!=pdPASS && ++params->timer_retries==TS_WS_QUEUE_RETRIES) { + params->timer_phase=phase==2?6:7; + TS_LOGE(TAG,"SSH timer drain retry limit; context retained until stop retry"); + return false; + } + if(ret==pdPASS)params->timer_retries=0; + return params->timer_phase!=5; +} +static void exec_retry_timer_drain(void) +{ + ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,0); + if(!op)return; + ssh_exec_task_params_t *params=ts_ws_op_data(op); + if(params){unsigned phase=params->timer_phase; + if(phase>=6){params->timer_retries=0;atomic_compare_exchange_strong(¶ms->timer_phase,&phase,phase==6?2:3);}} + ts_ws_op_release(op); +} +static void exec_destroy(void *data) +{ + ssh_exec_task_params_t *params=data;if(!params)return; + assert(!params->session && (!params->timer_phase || params->timer_phase==5)); + free((void*)params->config.host);free((void*)params->config.username); + if(params->password_owned){memset(params->password_owned,0,strlen(params->password_owned));free(params->password_owned);} + free(params->expect_pattern);free(params->fail_pattern);free(params->extract_pattern); + free(params->output_buffer);free(params->extracted_value); + vSemaphoreDelete(params->io);free(params); } /* SSH Exec 任务 */ @@ -1674,8 +1606,8 @@ static void ssh_exec_task(void *arg) char *key_buf = NULL; size_t key_len = 0; - /* 重置取消请求标志 */ - s_exec_cancel_requested = false; + ts_ws_stop_reason_t stop_reason=OP_STOP_NONE; + if(ts_ws_op_cancelled(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} TS_LOGI(TAG, "SSH exec task started: session_id=%lu, cmd=%s", (unsigned long)session_id, params->command); @@ -1690,67 +1622,94 @@ static void ssh_exec_task(void *arg) params->config.auth.key.private_key_path = NULL; params->config.auth.key.passphrase = NULL; } else { + stop_reason=ts_ws_op_business_end(params->op,false); + if(stop_reason){ret=ESP_ERR_TIMEOUT;goto execution_finished;} TS_LOGE(TAG, "Failed to load key '%s': %s", params->keyid, esp_err_to_name(ret)); /* 发送错误消息 */ - cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_exec_error"); - cJSON_AddNumberToObject(msg, "session_id", session_id); - cJSON_AddStringToObject(msg, "error", "Failed to load SSH key"); - char *json = cJSON_PrintUnformatted(msg); + if(ts_ws_op_close_begin(params->op)) { + cJSON *msg = cJSON_CreateObject(); + bool encoded=msg!=NULL; + encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_error"))!=NULL && encoded; + encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; + encoded = (cJSON_AddStringToObject(msg, "error", "Failed to load SSH key"))!=NULL && encoded; + char *json = encoded?cJSON_PrintUnformatted(msg):NULL; cJSON_Delete(msg); - if (json) { ts_webui_broadcast(json); free(json); } + ts_ws_op_close_finish(params->op,json); free(json); + } goto cleanup; } } + if(ts_ws_op_cancelled(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + /* 创建 SSH 会话 */ - ret = ts_ssh_session_create(¶ms->config, &s_exec_session); + ts_ssh_session_t created=NULL; + ret = ts_ssh_session_create(¶ms->config, &created); + xSemaphoreTake(params->io,portMAX_DELAY);params->session=created;xSemaphoreGive(params->io); if (ret != ESP_OK) { + stop_reason=ts_ws_op_business_end(params->op,false); + if(stop_reason){ret=ESP_ERR_TIMEOUT;goto execution_finished;} TS_LOGE(TAG, "Failed to create SSH session: %s", esp_err_to_name(ret)); + if(ts_ws_op_close_begin(params->op)) { cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_exec_error"); - cJSON_AddNumberToObject(msg, "session_id", session_id); - cJSON_AddStringToObject(msg, "error", "Failed to create SSH session"); - char *json = cJSON_PrintUnformatted(msg); + bool encoded=msg!=NULL; + encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_error"))!=NULL && encoded; + encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; + encoded = (cJSON_AddStringToObject(msg, "error", "Failed to create SSH session"))!=NULL && encoded; + char *json = encoded?cJSON_PrintUnformatted(msg):NULL; cJSON_Delete(msg); - if (json) { ts_webui_broadcast(json); free(json); } + ts_ws_op_close_finish(params->op,json); free(json); + } goto cleanup; } /* 连接 */ - ret = ts_ssh_connect(s_exec_session); + ret = ts_ssh_connect(params->session); if (ret != ESP_OK) { - const char *err = ts_ssh_get_error(s_exec_session); + stop_reason=ts_ws_op_business_end(params->op,ret==ESP_ERR_TIMEOUT); + if(stop_reason)goto execution_finished; + const char *err = ts_ssh_get_error(params->session); TS_LOGE(TAG, "SSH connect failed: %s", err ? err : "unknown"); + if(ts_ws_op_close_begin(params->op)) { cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_exec_error"); - cJSON_AddNumberToObject(msg, "session_id", session_id); - cJSON_AddStringToObject(msg, "error", err ? err : "Connection failed"); - char *json = cJSON_PrintUnformatted(msg); + bool encoded=msg!=NULL; + encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_error"))!=NULL && encoded; + encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; + encoded = (cJSON_AddStringToObject(msg, "error", err ? err : "Connection failed"))!=NULL && encoded; + char *json = encoded?cJSON_PrintUnformatted(msg):NULL; cJSON_Delete(msg); - if (json) { ts_webui_broadcast(json); free(json); } + ts_ws_op_close_finish(params->op,json); free(json); + } goto cleanup; } + if(ts_ws_op_cancelled(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + /* 发送开始消息 */ { + ts_ws_output_ticket_t start_ticket; + if(ts_ws_op_output_begin(params->op,&start_ticket)) { + if(start_ticket.count) { cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "ssh_exec_start"); - cJSON_AddNumberToObject(msg, "session_id", session_id); - cJSON_AddStringToObject(msg, "command", params->command); + bool encoded=msg!=NULL; + encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_start"))!=NULL && encoded; + encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; + encoded = (cJSON_AddStringToObject(msg, "command", params->command))!=NULL && encoded; /* 添加配置信息 */ if (params->expect_pattern) { - cJSON_AddStringToObject(msg, "expect_pattern", params->expect_pattern); + encoded = (cJSON_AddStringToObject(msg, "expect_pattern", params->expect_pattern))!=NULL && encoded; } if (params->fail_pattern) { - cJSON_AddStringToObject(msg, "fail_pattern", params->fail_pattern); + encoded = (cJSON_AddStringToObject(msg, "fail_pattern", params->fail_pattern))!=NULL && encoded; } if (params->extract_pattern) { - cJSON_AddStringToObject(msg, "extract_pattern", params->extract_pattern); + encoded = (cJSON_AddStringToObject(msg, "extract_pattern", params->extract_pattern))!=NULL && encoded; } - char *json = cJSON_PrintUnformatted(msg); + char *json = encoded?cJSON_PrintUnformatted(msg):NULL; cJSON_Delete(msg); - if (json) { ts_webui_broadcast(json); free(json); } + ts_ws_op_output_finish(&start_ticket,json); free(json); + } else ts_ws_op_output_finish(&start_ticket,NULL); + } } /* 判断是否需要启动超时定时器 */ @@ -1768,40 +1727,33 @@ static void ssh_exec_task(void *arg) (unsigned long)params->timeout_ms, need_timeout, params->stop_on_match); if (need_timeout && params->timeout_ms > 0) { - /* 创建或重置超时定时器 */ - if (s_exec_timeout_timer == NULL) { - s_exec_timeout_timer = xTimerCreate("ssh_timeout", - pdMS_TO_TICKS(params->timeout_ms), - pdFALSE, /* 单次触发 */ - NULL, - ssh_exec_timeout_callback); - } else { - /* 更新超时时间 */ - xTimerChangePeriod(s_exec_timeout_timer, pdMS_TO_TICKS(params->timeout_ms), 0); - } - - if (s_exec_timeout_timer) { - xTimerStart(s_exec_timeout_timer, 0); - TS_LOGI(TAG, "SSH exec timeout timer started: %lu ms", (unsigned long)params->timeout_ms); - } + ts_ws_op_retain(params->op); + params->timer=xTimerCreate("ssh_timeout",pdMS_TO_TICKS(params->timeout_ms),pdFALSE,params,ssh_exec_timeout_callback); + if(params->timer){params->timer_phase=1; + if(xTimerStart(params->timer,0)!=pdPASS)TS_LOGW(TAG,"SSH timeout timer could not start"); + } else ts_ws_op_release(params->op); } - - /* 流式执行命令 */ - ret = ts_ssh_exec_stream(s_exec_session, params->command, + + /* This lock-ordered claim is the conservative irreversible boundary. + * After it, cancellation is cooperative: remote execution may have begun. */ + if(!ts_ws_op_claim_submit(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + ret = ts_ssh_exec_stream(params->session, params->command, ssh_exec_output_callback, - (void *)(uintptr_t)session_id, + params, &exit_code); - /* 停止超时定时器 */ - if (s_exec_timeout_timer) { - xTimerStop(s_exec_timeout_timer, 0); - } - +execution_finished: + TS_WS_TEST_POINT("C04"); + stop_reason=ts_ws_op_business_end(params->op,ret==ESP_ERR_TIMEOUT); + TS_WS_TEST_POINT("C05"); + xSemaphoreTake(params->io,portMAX_DELAY);params->timer_closing=true;xSemaphoreGive(params->io); + if(params->timer_phase==1){params->timer_phase=2;ts_ws_subscriptions_wake();} + /* 处理模式匹配和状态判断 */ ts_webui_ssh_status_t status = TS_WEBUI_SSH_STATUS_SUCCESS; /* 检查是否因超时被取消 */ - bool was_timeout = s_exec_cancel_requested && (ret == ESP_ERR_TIMEOUT); + bool was_timeout = stop_reason==OP_STOP_TIMEOUT; /* 优先使用实时匹配结果 */ bool expect_matched = params->expect_matched; @@ -1809,7 +1761,11 @@ static void ssh_exec_task(void *arg) char *extracted_value = params->extracted_value; params->extracted_value = NULL; /* 转移所有权,避免重复释放 */ - if (was_timeout && !params->match_found) { + if(stop_reason==OP_STOP_USER) { + status=TS_WEBUI_SSH_STATUS_CANCELLED; + } else if(stop_reason==OP_STOP_MATCH) { + status=params->fail_matched?TS_WEBUI_SSH_STATUS_MATCH_FAILED:TS_WEBUI_SSH_STATUS_MATCH_SUCCESS; + } else if (was_timeout && !params->match_found) { /* 超时且未匹配成功 */ status = TS_WEBUI_SSH_STATUS_TIMEOUT; TS_LOGW(TAG, "SSH exec timed out without match"); @@ -1949,13 +1905,15 @@ static void ssh_exec_task(void *arg) /* 发送完成消息 */ { + if(ts_ws_op_close_begin(params->op)) { cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", - status == TS_WEBUI_SSH_STATUS_CANCELLED ? "ssh_exec_cancelled" : "ssh_exec_done"); - cJSON_AddNumberToObject(msg, "session_id", session_id); + bool encoded=msg!=NULL; + encoded = (cJSON_AddStringToObject(msg, "type", + status == TS_WEBUI_SSH_STATUS_CANCELLED ? "ssh_exec_cancelled" : "ssh_exec_done"))!=NULL && encoded; + encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; if (status != TS_WEBUI_SSH_STATUS_CANCELLED) { - cJSON_AddNumberToObject(msg, "exit_code", exit_code); + encoded = (cJSON_AddNumberToObject(msg, "exit_code", exit_code))!=NULL && encoded; /* 状态字符串 */ const char *status_str = "unknown"; @@ -1967,35 +1925,36 @@ static void ssh_exec_task(void *arg) case TS_WEBUI_SSH_STATUS_MATCH_FAILED: status_str = "match_failed"; break; default: break; } - cJSON_AddStringToObject(msg, "status", status_str); + encoded = (cJSON_AddStringToObject(msg, "status", status_str))!=NULL && encoded; /* 简单的成功标志 */ bool is_success = (status == TS_WEBUI_SSH_STATUS_SUCCESS || status == TS_WEBUI_SSH_STATUS_MATCH_SUCCESS); - cJSON_AddBoolToObject(msg, "success", is_success); + encoded = (cJSON_AddBoolToObject(msg, "success", is_success))!=NULL && encoded; /* 模式匹配结果 */ if (params->expect_pattern) { - cJSON_AddBoolToObject(msg, "expect_matched", expect_matched); + encoded = (cJSON_AddBoolToObject(msg, "expect_matched", expect_matched))!=NULL && encoded; } if (params->fail_pattern) { - cJSON_AddBoolToObject(msg, "fail_matched", fail_matched); + encoded = (cJSON_AddBoolToObject(msg, "fail_matched", fail_matched))!=NULL && encoded; } /* 提取的值 */ if (extracted_value) { - cJSON_AddStringToObject(msg, "extracted", extracted_value); + encoded = (cJSON_AddStringToObject(msg, "extracted", extracted_value))!=NULL && encoded; } /* 错误信息 */ if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { - cJSON_AddStringToObject(msg, "error", ts_ssh_get_error(s_exec_session)); + encoded = (cJSON_AddStringToObject(msg, "error", ts_ssh_get_error(params->session)))!=NULL && encoded; } } - char *json = cJSON_PrintUnformatted(msg); + char *json = encoded?cJSON_PrintUnformatted(msg):NULL; cJSON_Delete(msg); - if (json) { ts_webui_broadcast(json); free(json); } + ts_ws_op_close_finish(params->op,json); free(json); + } } /* 释放提取的值 */ @@ -2004,135 +1963,26 @@ static void ssh_exec_task(void *arg) } cleanup: + ts_ws_op_business_end(params->op,false); /* 清理密钥缓冲区 */ if (key_buf) { memset(key_buf, 0, key_len); free(key_buf); } - /* 断开并销毁会话 */ - if (s_exec_session) { - ts_ssh_disconnect(s_exec_session); - ts_ssh_session_destroy(s_exec_session); - s_exec_session = NULL; - } - - /* 清理参数 */ - if (params) { - free(params->expect_pattern); - free(params->fail_pattern); - free(params->extract_pattern); - free(params->output_buffer); - free(params); - } - s_exec_params = NULL; - - s_exec_running = false; - s_exec_task = NULL; - + xSemaphoreTake(params->io,portMAX_DELAY); + params->timer_closing=true; + if(params->session){ts_ssh_disconnect(params->session);ts_ssh_session_destroy(params->session);params->session=NULL;} + xSemaphoreGive(params->io); + if(params->timer_phase==1)params->timer_phase=2; + ts_ws_op_executor_done(params->op); + TS_LOGI(TAG, "SSH exec task ended: session_id=%lu", (unsigned long)session_id); vTaskDelete(NULL); } -esp_err_t ts_webui_ssh_exec_start(const char *host, uint16_t port, - const char *user, const char *keyid, - const char *password, const char *command, - uint32_t *session_id) -{ - if (!host || !user || !command) { - return ESP_ERR_INVALID_ARG; - } - - /* 检查是否有正在运行的会话 */ - if (s_exec_running) { - TS_LOGW(TAG, "SSH exec session already running"); - return ESP_ERR_INVALID_STATE; - } - - /* 分配任务参数 */ - ssh_exec_task_params_t *params = heap_caps_calloc(1, sizeof(ssh_exec_task_params_t), - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!params) params = calloc(1, sizeof(ssh_exec_task_params_t)); - if (!params) { - return ESP_ERR_NO_MEM; - } - - /* 生成会话 ID */ - s_exec_session_id++; - if (s_exec_session_id == 0) s_exec_session_id = 1; /* 避免 0 */ - - /* 配置 SSH */ - params->config = (ts_ssh_config_t)TS_SSH_DEFAULT_CONFIG(); - params->config.host = strdup(host); - params->config.port = port; - params->config.username = strdup(user); - params->config.timeout_ms = 30000; - params->session_id = s_exec_session_id; - - /* 存储命令 */ - strncpy(params->command, command, sizeof(params->command) - 1); - - /* 配置认证方式 */ - if (keyid && keyid[0]) { - strncpy(params->keyid, keyid, sizeof(params->keyid) - 1); - /* 实际密钥加载在任务中完成 */ - } else if (password && password[0]) { - params->config.auth_method = TS_SSH_AUTH_PASSWORD; - params->config.auth.password = strdup(password); - } else { - free((void *)params->config.host); - free((void *)params->config.username); - free(params); - return ESP_ERR_INVALID_ARG; - } - - /* 默认启用输出收集 */ - params->collect_output = true; - params->max_output_size = 64 * 1024; /* 默认 64KB */ - - /* 分配输出缓冲区 */ - params->output_capacity = params->max_output_size; - params->output_buffer = heap_caps_malloc(params->output_capacity, - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!params->output_buffer) { - params->output_buffer = malloc(params->output_capacity); - } - if (params->output_buffer) { - params->output_buffer[0] = '\0'; - params->output_len = 0; - } - - s_exec_running = true; - s_exec_params = params; /* 设置全局指针供回调访问 */ - - /* 创建任务 - MUST use DRAM stack because keystore access requires NVS. - * SPI Flash operations disable cache, and PSRAM access requires cache. - */ - BaseType_t ret = xTaskCreate(ssh_exec_task, "ssh_exec", 8192, params, 5, &s_exec_task); - if (ret != pdPASS) { - TS_LOGE(TAG, "Failed to create SSH exec task"); - s_exec_running = false; - s_exec_params = NULL; - free((void *)params->config.host); - free((void *)params->config.username); - if (params->config.auth.password) free((void *)params->config.auth.password); - free(params->output_buffer); - free(params); - return ESP_FAIL; - } - - if (session_id) { - *session_id = s_exec_session_id; - } - - TS_LOGI(TAG, "SSH exec started: session_id=%lu, host=%s, cmd=%s", - (unsigned long)s_exec_session_id, host, command); - - return ESP_OK; -} - /* 带选项的扩展版本 */ -esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, +static esp_err_t ts_webui_ssh_exec_start_ex_impl(ts_ws_operation_t *op, const char *host, uint16_t port, const char *user, const char *keyid, const char *password, const char *command, const ts_webui_ssh_options_t *options, @@ -2142,12 +1992,6 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, return ESP_ERR_INVALID_ARG; } - /* 检查是否有正在运行的会话 */ - if (s_exec_running) { - TS_LOGW(TAG, "SSH exec session already running"); - return ESP_ERR_INVALID_STATE; - } - /* 分配任务参数 */ ssh_exec_task_params_t *params = heap_caps_calloc(1, sizeof(ssh_exec_task_params_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); @@ -2156,17 +2000,21 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, return ESP_ERR_NO_MEM; } - /* 生成会话 ID */ - s_exec_session_id++; - if (s_exec_session_id == 0) s_exec_session_id = 1; - + params->op=op;params->session_id=ts_ws_op_id(op); + params->io=xSemaphoreCreateMutex(); + if(!params->io){free(params);return ESP_ERR_NO_MEM;} + ts_ws_op_bind(op,params,exec_destroy); + ts_ws_op_set_maintenance(op,exec_maintenance); + /* 配置 SSH */ params->config = (ts_ssh_config_t)TS_SSH_DEFAULT_CONFIG(); + params->config.cancelled=ts_ws_op_cancelled; + params->config.cancel_context=op; params->config.host = strdup(host); params->config.port = port; params->config.username = strdup(user); params->config.timeout_ms = (options && options->timeout_ms > 0) ? options->timeout_ms : 30000; - params->session_id = s_exec_session_id; + /* 存储命令 */ strncpy(params->command, command, sizeof(params->command) - 1); @@ -2176,14 +2024,14 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, strncpy(params->keyid, keyid, sizeof(params->keyid) - 1); } else if (password && password[0]) { params->config.auth_method = TS_SSH_AUTH_PASSWORD; - params->config.auth.password = strdup(password); + params->password_owned=strdup(password); + params->config.auth.password=params->password_owned; } else { - free((void *)params->config.host); - free((void *)params->config.username); - free(params); - return ESP_ERR_INVALID_ARG; + return ESP_ERR_INVALID_ARG; /* operation destructor owns partially built params */ } - + if(!params->config.host || !params->config.username || + (password && password[0] && !params->keyid[0] && !params->password_owned))return ESP_ERR_NO_MEM; + /* 配置可选参数 */ if (options) { if (options->expect_pattern && options->expect_pattern[0]) { @@ -2237,8 +2085,7 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, } } - s_exec_running = true; - s_exec_params = params; + /* 命令开始时初始化所有变量(重置旧值) */ TS_LOGI(TAG, "Checking var_name for init: '%s' (len=%d)", @@ -2308,33 +2155,48 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, /* 创建任务 - MUST use DRAM stack because keystore access requires NVS. * SPI Flash operations disable cache, and PSRAM access requires cache. */ - BaseType_t ret = xTaskCreate(ssh_exec_task, "ssh_exec", 8192, params, 5, &s_exec_task); - if (ret != pdPASS) { - TS_LOGE(TAG, "Failed to create SSH exec task"); - s_exec_running = false; - s_exec_params = NULL; - free((void *)params->config.host); - free((void *)params->config.username); - if (params->config.auth.password) free((void *)params->config.auth.password); - free(params->expect_pattern); - free(params->fail_pattern); - free(params->extract_pattern); - free(params->output_buffer); - free(params); + /* Task may finish before task-create returns: creator still owns params. */ + ts_ws_op_executor_take(op); + ts_ws_op_open(op); + BaseType_t ret=xTaskCreate(ssh_exec_task,"ssh_exec",8192,params,5,NULL); + if(ret!=pdPASS){ + ts_ws_op_executor_done(op); + ts_ws_op_discard(op); return ESP_FAIL; } - + if (session_id) { - *session_id = s_exec_session_id; + *session_id = params->session_id; } TS_LOGI(TAG, "SSH exec started (extended): session_id=%lu, host=%s, cmd=%s, expect=%s", - (unsigned long)s_exec_session_id, host, command, + (unsigned long)params->session_id, host, command, params->expect_pattern ? params->expect_pattern : "(none)"); return ESP_OK; } +esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, + const char *user, const char *keyid, + const char *password, const char *command, + const ts_webui_ssh_options_t *options, + uint32_t *session_id) +{ + esp_err_t admission; + ts_ws_operation_t *op=ts_ws_op_create(TS_WS_OP_EXEC,(ts_ws_peer_t){0},&admission); + if(!op)return admission; + esp_err_t ret=ts_webui_ssh_exec_start_ex_impl(op,host,port,user,keyid,password,command,options,session_id); + if(ret!=ESP_OK && ts_ws_op_starting(op))ts_ws_op_discard(op); + ts_ws_op_executor_done(op); + return ret; +} + +esp_err_t ts_webui_ssh_exec_start(const char *host,uint16_t port,const char *user, + const char *keyid,const char *password,const char *command,uint32_t *session_id) +{ + return ts_webui_ssh_exec_start_ex(host,port,user,keyid,password,command,NULL,session_id); +} + /* 释放结果结构 */ void ts_webui_ssh_result_free(ts_webui_ssh_result_t *result) { @@ -2347,19 +2209,17 @@ void ts_webui_ssh_result_free(ts_webui_ssh_result_t *result) esp_err_t ts_webui_ssh_exec_cancel(uint32_t session_id) { - if (!s_exec_running || session_id != s_exec_session_id) { - return ESP_ERR_INVALID_STATE; - } - - if (s_exec_session) { - ts_ssh_abort(s_exec_session); - TS_LOGI(TAG, "SSH exec cancel requested: session_id=%lu", (unsigned long)session_id); - } - - return ESP_OK; + ts_ws_operation_t *op=ts_ws_op_cancel_exec(session_id); + if(!op)return ESP_ERR_INVALID_STATE; + ssh_exec_task_params_t *params=ts_ws_op_data(op); + exec_abort(params); /* intent is already persistent, even without a session */ + ts_ws_op_release(op); + return ESP_OK; /* accepted request, not remote termination confirmation */ } bool ts_webui_ssh_exec_is_running(uint32_t session_id) { - return s_exec_running && (session_id == 0 || session_id == s_exec_session_id); + ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,session_id); + if(!op)return false; + bool running=ts_ws_op_business_running(op);ts_ws_op_release(op);return running; } diff --git a/components/ts_webui/src/ts_ws_operation.c b/components/ts_webui/src/ts_ws_operation.c new file mode 100644 index 0000000..6b5968c --- /dev/null +++ b/components/ts_webui/src/ts_ws_operation.c @@ -0,0 +1,276 @@ +#include "ts_ws_operation.h" +#include "ts_ws_subscriptions.h" +#include "freertos/FreeRTOS.h" +#include +#include +#include + +#define OP_OUTPUT_TARGETS (2 * TS_WS_CONNECTIONS) +typedef struct { uint64_t id; bool active; } op_target_t; +struct ts_ws_operation { + ts_ws_op_stats_t ledger; + ts_ws_op_kind_t kind; + bool initializing, builder; + bool business_accepted; + ts_ws_business_phase_t business; + ts_ws_stop_reason_t first_stop; + unsigned stop_reasons; + ts_ws_peer_t peer, terminal_peers[TS_WS_CONNECTIONS]; + unsigned terminal_count; + ts_ws_reservation_t terminal; + op_target_t output[OP_OUTPUT_TARGETS], final[TS_WS_CONNECTIONS]; + void *data; + void (*destroy)(void *); + bool (*maintain)(void *); +}; +static portMUX_TYPE s_op_lock = portMUX_INITIALIZER_UNLOCKED; +static ts_ws_operation_t s_ops[TS_WS_OP_KINDS]; +static uint64_t s_op_sequence, s_op_delivery; +static bool s_op_accepting, s_op_tick; +#define OP_LOCK() portENTER_CRITICAL(&s_op_lock) +#define OP_UNLOCK() portEXIT_CRITICAL(&s_op_lock) + +void ts_ws_op_enable(void) { OP_LOCK(); s_op_accepting=true; OP_UNLOCK(); } +void ts_ws_op_stop_admission(void) { OP_LOCK(); s_op_accepting=false; OP_UNLOCK(); } +bool ts_ws_op_busy(void) { + OP_LOCK(); bool busy=false; + for(unsigned i=0;i=TS_WS_OP_KINDS)return NULL; + if(error)*error=ESP_ERR_INVALID_STATE; + OP_LOCK(); ts_ws_operation_t *op=&s_ops[kind]; + if(!s_op_accepting || op->ledger.phase!=OP_FREE || s_op_sequence==UINT32_MAX) { OP_UNLOCK(); return NULL; } + *op=(ts_ws_operation_t){.kind=kind,.peer=peer,.initializing=true, + .ledger={.phase=OP_STARTING,.identity=++s_op_sequence,.refs=1,.executors=1}}; + OP_UNLOCK(); + esp_err_t ret=kind==TS_WS_OP_SHELL ? ts_ws_reserve(&peer,1,true,4096,&op->terminal) : + ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&op->terminal); + OP_LOCK(); op->initializing=false; OP_UNLOCK(); + if(error)*error=ret; + if(ret!=ESP_OK) { ts_ws_op_discard(op); ts_ws_op_executor_done(op); return NULL; } + return op; +} +void ts_ws_op_bind(ts_ws_operation_t *op,void *data,void (*destroy)(void *)) { + OP_LOCK(); assert(op->ledger.phase==OP_STARTING && !op->data);op->data=data;op->destroy=destroy;OP_UNLOCK(); +} +void ts_ws_op_set_maintenance(ts_ws_operation_t *op,bool (*maintain)(void *)) {OP_LOCK();op->maintain=maintain;OP_UNLOCK();} +bool ts_ws_op_needs_tick(void) {OP_LOCK();bool yes=s_op_tick;OP_UNLOCK();return yes;} +void *ts_ws_op_data(ts_ws_operation_t *op) { OP_LOCK();void *p=op->data;OP_UNLOCK();return p; } +uint32_t ts_ws_op_id(ts_ws_operation_t *op) { return (uint32_t)op->ledger.identity; } +ts_ws_peer_t ts_ws_op_peer(ts_ws_operation_t *op) { return op->peer; } +ts_ws_operation_t *ts_ws_op_acquire(ts_ws_op_kind_t kind,uint32_t id) { + OP_LOCK();ts_ws_operation_t *op=&s_ops[kind]; + if(op->initializing || op->ledger.phase==OP_FREE || op->ledger.phase==OP_RECLAIMING || (id && op->ledger.identity!=id))op=NULL; + else op->ledger.refs++; + OP_UNLOCK();return op; +} +void ts_ws_op_retain(ts_ws_operation_t *op) { OP_LOCK();assert(op->ledger.refs);op->ledger.refs++;OP_UNLOCK(); } +void ts_ws_op_release(ts_ws_operation_t *op) { + OP_LOCK();assert(op->ledger.refs);op->ledger.refs--;OP_UNLOCK();ts_ws_subscriptions_wake(); +} +void ts_ws_op_executor_take(ts_ws_operation_t *op) { + OP_LOCK();assert(op->ledger.refs);op->ledger.refs++;op->ledger.executors++;OP_UNLOCK(); +} +void ts_ws_op_executor_done(ts_ws_operation_t *op) { + OP_LOCK();assert(op->ledger.executors && op->ledger.refs);op->ledger.executors--;op->ledger.refs--;OP_UNLOCK();ts_ws_subscriptions_wake(); +} +bool ts_ws_op_executing(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.executors!=0;OP_UNLOCK();return yes; } +bool ts_ws_op_open(ts_ws_operation_t *op) { + OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;if(yes){op->ledger.phase=OP_OPEN;op->business_accepted=true;}OP_UNLOCK();return yes; +} +bool ts_ws_op_is_open(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.phase==OP_OPEN;OP_UNLOCK();return yes; } +bool ts_ws_op_starting(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;OP_UNLOCK();return yes; } +void ts_ws_op_discard(ts_ws_operation_t *op) { + OP_LOCK();assert((op->ledger.phase==OP_STARTING || op->ledger.phase==OP_OPEN) && !op->ledger.preparing && !op->ledger.unsettled);op->ledger.phase=OP_FINALIZING;OP_UNLOCK(); + ts_ws_reservation_release(&op->terminal); + OP_LOCK();op->ledger.phase=OP_TERMINAL_SETTLED;OP_UNLOCK(); +} +/* Caller holds a ref. The winner takes a second ref for snapshot/encoding. */ +static bool close_locked(ts_ws_operation_t *op) { + if(op->ledger.phase!=OP_OPEN && op->ledger.phase!=OP_STARTING)return false; + op->ledger.phase=OP_CLOSING;op->builder=true;op->ledger.refs++;return true; +} +static void close_snapshot(ts_ws_operation_t *op) { + if(op->kind==TS_WS_OP_SHELL){op->terminal_peers[0]=op->peer;op->terminal_count=1;} + else op->terminal_count=ts_ws_peer_snapshot(op->terminal_peers,TS_WS_CONNECTIONS); +} +bool ts_ws_op_close_begin(ts_ws_operation_t *op) { + OP_LOCK();bool winner=close_locked(op);OP_UNLOCK(); + if(winner){close_snapshot(op);TS_WS_TEST_POINT("B07");}return winner; +} +static void fallback(ts_ws_operation_t *op,char *text,size_t size,bool failed) { + const char *reason=failed ? "SSH output delivery incomplete; remote command result is not confirmed" : "SSH result delivery failed; result is unknown"; + if(op->kind==TS_WS_OP_SHELL && !failed)reason="SSH status delivery failed"; + if(op->kind==TS_WS_OP_SHELL)snprintf(text,size,"{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"%s\"}",reason); + else snprintf(text,size,"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"%s\"}",(unsigned long)ts_ws_op_id(op),reason); +} +void ts_ws_op_close_finish(ts_ws_operation_t *op,const char *json) { + char text[256];fallback(op,text,sizeof(text),false); + if(!json || ts_ws_reserved_text(&op->terminal,json)!=ESP_OK)ts_ws_reserved_text(&op->terminal,text); + OP_LOCK();assert(op->builder);op->builder=false;assert(op->ledger.refs);op->ledger.refs--;OP_UNLOCK();ts_ws_subscriptions_wake(); +} +static void fail_locked(ts_ws_operation_t *op,bool *winner) { + op->ledger.failed=true;*winner=close_locked(op); +} +static void settle_target(uint64_t identity,uint64_t token,esp_err_t result) { + ts_ws_operation_t *op=NULL;bool winner=false,terminal=false; + OP_LOCK(); + for(unsigned i=0;ioutput[i].active && op->output[i].id==token){record=&op->output[i];break;} + if(!record)for(unsigned i=0;ifinal[i].active && op->final[i].id==token){record=&op->final[i];terminal=true;break;} + } + if(!record){if(op)op->ledger.duplicates++;OP_UNLOCK();return;} + record->active=false; + if(terminal){assert(op->ledger.terminals);op->ledger.terminals--;} + else { + if(result!=ESP_OK)fail_locked(op,&winner); + assert(op->ledger.unsettled);op->ledger.unsettled--;op->ledger.settled++; + } + /* Target ref becomes the callback ref; not dropped at counter decrement. */ + OP_UNLOCK(); + if(winner){close_snapshot(op);ts_ws_op_close_finish(op,NULL);} + TS_WS_TEST_POINT("B06"); + ts_ws_op_release(op); /* final access: old callback cannot enter replacement */ +} +bool ts_ws_op_output_begin(ts_ws_operation_t *op,ts_ws_output_ticket_t *t) { + *t=(ts_ws_output_ticket_t){0};TS_WS_TEST_POINT("B01"); + OP_LOCK();bool ok=op->ledger.phase==OP_OPEN; + if(ok){op->ledger.preparing++;t->sequence=++op->ledger.tickets;op->ledger.refs++;t->op=op;}OP_UNLOCK(); + if(!ok)return false; + if(op->kind==TS_WS_OP_SHELL){t->peers[0]=op->peer;t->count=1;} + else t->count=ts_ws_peer_snapshot(t->peers,TS_WS_CONNECTIONS); + TS_WS_TEST_POINT("B02");return true; +} +void ts_ws_op_output_finish(ts_ws_output_ticket_t *t,const char *json) { + if(!t->op)return; + ts_ws_operation_t *op=t->op;ts_ws_message_t *m=NULL; + if(t->count && json)m=ts_ws_message_text(json,strlen(json)); + uint64_t tokens[TS_WS_CONNECTIONS]={0};bool winner=false,registered=false; + TS_WS_TEST_POINT("B03"); + OP_LOCK(); + unsigned available=0;for(unsigned i=0;ioutput[i].active; + if(t->count && (!m || availablecount || s_op_delivery>UINT64_MAX-t->count))fail_locked(op,&winner); + else { + for(unsigned i=0,j=0;icount;i++)if(!op->output[i].active){ + tokens[j++]=++s_op_delivery;op->output[i]=(op_target_t){s_op_delivery,true}; + } + op->ledger.unsettled+=t->count;op->ledger.registered+=t->count;op->ledger.refs+=t->count;registered=true; + } + OP_UNLOCK(); + if(winner){close_snapshot(op);ts_ws_op_close_finish(op,NULL);} + TS_WS_TEST_POINT("B04"); + if(registered)for(unsigned i=0;icount;i++) { + esp_err_t ret=ts_ws_transport_submit(t->peers[i],m,op->ledger.identity,tokens[i],NULL,settle_target); + if(ret!=ESP_OK)settle_target(op->ledger.identity,tokens[i],ret); + } + ts_ws_message_release(m); + OP_LOCK();assert(op->ledger.preparing);op->ledger.preparing--;op->ledger.finished++;OP_UNLOCK(); + t->op=NULL;ts_ws_op_release(op); /* entire publication, including early done */ +} +void ts_ws_op_poll(void) { + bool tick=false; + for(unsigned k=0;kmaintain && op->ledger.phase>=OP_OPEN && op->ledger.phaseledger.refs++; + OP_UNLOCK(); + if(maintain){tick |= op->maintain(op->data);OP_LOCK();assert(op->ledger.refs);op->ledger.refs--;OP_UNLOCK();} + OP_LOCK(); + if(op->ledger.phase==OP_CLOSING && !op->builder && !op->ledger.preparing && !op->ledger.unsettled) { + op->ledger.phase=OP_FINALIZING;op->ledger.refs++;op->ledger.finalizers++; + r=op->terminal;op->terminal=(ts_ws_reservation_t){0};finalize=true; + } + OP_UNLOCK(); + if(finalize) { + char text[256]; + if(op->ledger.failed){fallback(op,text,sizeof(text),true);ts_ws_reserved_text(&r,text);} + OP_LOCK(); + unsigned n=op->terminal_count; + if(s_op_delivery>UINT64_MAX-n)n=0; /* lifetime exhaustion: no token reuse */ + for(unsigned i=0;ifinal[i]=(op_target_t){tokens[i],true};} + op->ledger.terminals=n;op->ledger.refs+=n;op->ledger.phase=OP_TERMINAL_PENDING; + OP_UNLOCK(); + for(unsigned i=0;iterminal_peers[i],op->ledger.identity,tokens[i],settle_target); + if(ret!=ESP_OK)settle_target(op->ledger.identity,tokens[i],ret); + TS_WS_TEST_POINT("B08"); + } + ts_ws_reservation_release(&r);ts_ws_op_release(op); + } + OP_LOCK(); + if(op->ledger.phase==OP_TERMINAL_PENDING && !op->ledger.terminals)op->ledger.phase=OP_TERMINAL_SETTLED; + if(op->ledger.phase==OP_TERMINAL_SETTLED && !op->ledger.refs) { + assert(!op->ledger.executors && !op->ledger.preparing && !op->ledger.unsettled && !op->terminal.message); + op->ledger.phase=OP_RECLAIMING;retire=true; + } + OP_UNLOCK(); + if(retire) { + TS_WS_TEST_POINT("B10");if(op->destroy)op->destroy(op->data); + OP_LOCK();op->data=NULL;op->destroy=NULL;op->maintain=NULL;op->ledger.phase=OP_FREE;OP_UNLOCK(); + } + } + OP_LOCK();s_op_tick=tick;OP_UNLOCK(); +} +void ts_ws_op_stats(ts_ws_op_kind_t kind,ts_ws_op_stats_t *stats) {OP_LOCK();*stats=s_ops[kind].ledger;OP_UNLOCK();} + +/* All identity checks, reference acquisition and control decisions linearize + * under the same operation lock. No resource or network work under this lock. */ +static ts_ws_operation_t *shell_for_peer(ts_ws_peer_t peer,bool control) { + OP_LOCK();ts_ws_operation_t *op=&s_ops[TS_WS_OP_SHELL]; + if(op->initializing || op->ledger.phase==OP_FREE || op->ledger.phase==OP_RECLAIMING || + (control && op->ledger.phase!=OP_OPEN) || !ts_ws_peer_equal(op->peer,peer))op=NULL; + else op->ledger.refs++; + OP_UNLOCK();return op; +} +ts_ws_operation_t *ts_ws_op_shell_control(ts_ws_peer_t peer) { + ts_ws_operation_t *op=shell_for_peer(peer,true);TS_WS_TEST_POINT("C01");return op; +} +ts_ws_operation_t *ts_ws_op_shell_connection(ts_ws_peer_t peer) { + return shell_for_peer(peer,false); +} +ts_ws_operation_t *ts_ws_op_shell_owner(void) { + return ts_ws_op_acquire(TS_WS_OP_SHELL,0); /* service/connection owner only */ +} +static bool request_stop_locked(ts_ws_operation_t *op,ts_ws_stop_reason_t reason) { + if(op->kind!=TS_WS_OP_EXEC || !op->business_accepted || op->business==OP_BUSINESS_ENDED)return false; + op->stop_reasons|=reason; + if(!op->first_stop)op->first_stop=reason; + return true; +} +ts_ws_operation_t *ts_ws_op_cancel_exec(uint32_t id) { + OP_LOCK();ts_ws_operation_t *op=&s_ops[TS_WS_OP_EXEC]; + if(!id || op->ledger.phase==OP_FREE || op->ledger.phase==OP_RECLAIMING || + op->ledger.identity!=id || !request_stop_locked(op,OP_STOP_USER))op=NULL; + else op->ledger.refs++; + OP_UNLOCK();return op; +} +bool ts_ws_op_request_stop(ts_ws_operation_t *op,ts_ws_stop_reason_t reason) { + OP_LOCK();bool accepted=request_stop_locked(op,reason);OP_UNLOCK();return accepted; +} +bool ts_ws_op_cancelled(void *context) { + ts_ws_operation_t *op=context;OP_LOCK();bool yes=op->stop_reasons!=0;OP_UNLOCK();return yes; +} +bool ts_ws_op_claim_submit(ts_ws_operation_t *op) { + TS_WS_TEST_POINT("C02");OP_LOCK(); + bool yes=op->business_accepted && op->business==OP_BUSINESS_PREPARING && !op->stop_reasons; + if(yes)op->business=OP_BUSINESS_SUBMITTED; + OP_UNLOCK();TS_WS_TEST_POINT("C03");return yes; +} +ts_ws_stop_reason_t ts_ws_op_business_end(ts_ws_operation_t *op,bool deadline) { + OP_LOCK(); + if(op->business!=OP_BUSINESS_ENDED){ + if(deadline && !op->first_stop)request_stop_locked(op,OP_STOP_TIMEOUT); + op->business=OP_BUSINESS_ENDED; + } + ts_ws_stop_reason_t reason=op->first_stop;OP_UNLOCK();return reason; +} +bool ts_ws_op_business_running(ts_ws_operation_t *op) { + OP_LOCK();bool yes=op->business_accepted && op->business!=OP_BUSINESS_ENDED;OP_UNLOCK();return yes; +} diff --git a/components/ts_webui/src/ts_ws_subscriptions.c b/components/ts_webui/src/ts_ws_subscriptions.c index 8ad8f51..508a5d3 100644 --- a/components/ts_webui/src/ts_ws_subscriptions.c +++ b/components/ts_webui/src/ts_ws_subscriptions.c @@ -1,654 +1,500 @@ -/** - * @file ts_ws_subscriptions.c - * @brief WebSocket Subscription Manager Implementation - */ - +/** Demand-driven display telemetry. Hardware sampling/control is not scheduled here. */ #include "ts_ws_subscriptions.h" -#include "ts_webui.h" -#include "ts_log.h" -#include "ts_event.h" +#include "ts_ws_transport.h" +#include "ts_ws_operation.h" #include "ts_api.h" +#include "ts_log.h" #include "esp_timer.h" #include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" +#include "freertos/task.h" +#include #include - -#define TAG "ws_subs" +#include #define MAX_SUBSCRIPTIONS 32 -#define MAX_TOPIC_LEN 32 - +#define EVENT_SLOTS 4 +#define WORKER_STACK 8192 +#define STOP_TIMEOUT_MS 6000 +#define TAG "ws_subs" +static const struct { const char *name; uint32_t interval; int metric; } topics[] = { + {"system.dashboard",1000,-1}, {"system.info",5000,2}, + {"system.memory",5000,1}, {"system.cpu",1000,0}, + {"network.status",5000,3}, {"power.status",5000,4}, + {"fan.status",5000,5}, {"service.list",5000,6}, + {"device.status",2000,-2}, {"ota.progress",1000,-2}, + {"config.pack.validated",0,-2} +}; +#define TOPIC_COUNT (sizeof(topics)/sizeof(topics[0])) +static const char *metrics[] = {"system.cpu","system.memory","system.info", + "network.status","power.status","fan.status","service.list"}; +static const char *fields[] = {"cpu","memory","info","network","power","fan","services"}; +typedef enum { OFF, STARTING, RUNNING, DRAINING, STOPPING } lifecycle_t; typedef struct { - int fd; // 客户端文件描述符 - char topic[MAX_TOPIC_LEN]; // 订阅的主题 - uint32_t min_interval_ms; // 最小推送间隔(去抖动) - int64_t last_broadcast_time; // 上次广播时间戳(微秒) - bool active; // 订阅是否激活 + ts_ws_peer_t peer; + uint64_t revision, pending; + int64_t last_success, next_attempt; + uint32_t interval; + unsigned topic; + bool active; } subscription_t; - typedef struct { - const char *topic; // 主题名称 - ts_event_base_t event_base; // 事件基础 - int32_t event_id; // 事件 ID - uint32_t default_min_interval_ms; // 默认最小间隔 -} topic_mapping_t; - -/* 订阅数组 */ -static subscription_t s_subscriptions[MAX_SUBSCRIPTIONS]; -static SemaphoreHandle_t s_subs_mutex = NULL; - -/* 事件处理器句柄 */ -static ts_event_handler_handle_t s_system_event_handle = NULL; -static ts_event_handler_handle_t s_device_event_handle = NULL; -static ts_event_handler_handle_t s_ota_event_handle = NULL; - -/* 定时器句柄 */ -static esp_timer_handle_t s_system_info_timer = NULL; /* 5s 间隔 */ -static esp_timer_handle_t s_cpu_stats_timer = NULL; /* 1s 间隔 */ -static esp_timer_handle_t s_dashboard_timer = NULL; /* 1s 间隔 - 聚合订阅 */ - -/* 主题映射表 */ -static const topic_mapping_t s_topic_map[] = { - {"system.dashboard", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 1000}, /* 聚合主题 */ - {"system.info", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, - {"system.memory", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, - {"system.cpu", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 1000}, - {"network.status", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, - {"power.status", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, - {"fan.status", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, - {"service.list", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, - {"device.status", TS_EVENT_BASE_DEVICE_MON, TS_EVENT_DEVICE_STATUS_CHANGED, 2000}, - {"ota.progress", TS_EVENT_BASE_OTA, TS_EVENT_OTA_PROGRESS_UPDATE, 1000}, - {"config.pack.validated", NULL, 0, 0}, /* 推送驱动主题 */ -}; -#define TOPIC_MAP_SIZE (sizeof(s_topic_map) / sizeof(s_topic_map[0])) - -/* 前向声明 */ -static void system_event_handler(const ts_event_t *event, void *user_data); -static void device_event_handler(const ts_event_t *event, void *user_data); -static void ota_event_handler(const ts_event_t *event, void *user_data); - -/*===========================================================================*/ -/* 辅助函数 */ -/*===========================================================================*/ + ts_ws_peer_t peer; + uint64_t revision, delivery; + unsigned topic; +} target_t; +typedef struct { + bool used, ready; + uint64_t order; + ts_ws_message_t *message; + uint64_t targets[MAX_SUBSCRIPTIONS]; +} event_item_t; +/* Stable storage / spinlock survive init/deinit. Only short value mutations + * and task notifications under lock, never heap, API, JSON, queue or network. */ +static portMUX_TYPE s_lock = portMUX_INITIALIZER_UNLOCKED; +static lifecycle_t s_state; +static bool s_stop_owner; +static TaskHandle_t s_worker; +static unsigned s_entries, s_outstanding; +static uint64_t s_sequence; +static unsigned s_topic_cursor, s_subscription_cursor; +static int64_t s_allocation_retry_at; +static subscription_t s_subs[MAX_SUBSCRIPTIONS]; +static event_item_t s_events[EVENT_SLOTS]; +static ts_event_handler_handle_t s_handlers[3]; +static struct { + uint64_t api[7], batches[TOPIC_COUNT], serialized[TOPIC_COUNT]; + uint64_t queued, success, failure, stale, event_dropped, idle_wait, capacity_wait; + uint32_t stack_low_water; +} s_stats; -/* 查找主题映射 */ -static const topic_mapping_t *find_topic_mapping(const char *topic) +static int64_t after_ms(int64_t now, uint32_t ms) { - for (int i = 0; i < TOPIC_MAP_SIZE; i++) { - if (strcmp(s_topic_map[i].topic, topic) == 0) { - return &s_topic_map[i]; - } - } - return NULL; + int64_t delta = (int64_t)ms * 1000; + return now > INT64_MAX - delta ? INT64_MAX : now + delta; } - -/* 检查是否需要广播(去抖动) */ -static bool should_broadcast(subscription_t *sub) +static void wake_locked(void) { if (s_worker) xTaskNotifyGive(s_worker); } +void ts_ws_subscriptions_wake(void) { - int64_t now = esp_timer_get_time(); - int64_t elapsed_ms = (now - sub->last_broadcast_time) / 1000; - return (elapsed_ms >= sub->min_interval_ms); + portENTER_CRITICAL(&s_lock);wake_locked();portEXIT_CRITICAL(&s_lock); } - -/* 查找或分配订阅槽位 */ -static subscription_t *find_or_alloc_subscription(int fd, const char *topic) +static int topic_id(const char *name) { - subscription_t *free_slot = NULL; - - // 查找已存在的订阅 - for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { - if (s_subscriptions[i].active && - s_subscriptions[i].fd == fd && - strcmp(s_subscriptions[i].topic, topic) == 0) { - return &s_subscriptions[i]; - } - if (!s_subscriptions[i].active && !free_slot) { - free_slot = &s_subscriptions[i]; - } - } - - return free_slot; + if (name) for (unsigned i=0;idata || event->data_size == 0) { - return; - } - - // 解析 JSON 字符串 - cJSON *data = cJSON_Parse((const char *)event->data); - if (data) { - ts_ws_broadcast_to_topic("device.status", data); - cJSON_Delete(data); - } + for (unsigned i=0;idata || event->data_size == 0) { - return; - } - - // 解析 JSON 字符串 - cJSON *data = cJSON_Parse((const char *)event->data); - if (data) { - ts_ws_broadcast_to_topic("ota.progress", data); - cJSON_Delete(data); - } + portENTER_CRITICAL(&s_lock); + subscription_t *s = find_revision(revision); + bool ok = (s_state == RUNNING || s_state == DRAINING) && s && s->pending == delivery; + portEXIT_CRITICAL(&s_lock); + return ok; } - -/* 定时器回调:定期发送系统信息 */ -static void system_info_timer_callback(void *arg) +static void delivery_done(uint64_t revision, uint64_t delivery, esp_err_t result) { - // 发送系统信息事件 - ts_event_post(TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, NULL, 0, 0); + int64_t now = esp_timer_get_time(); + portENTER_CRITICAL(&s_lock); + subscription_t *s = find_revision(revision); + if (s && s->pending == delivery) { + s->pending = 0; + if (result == ESP_OK) s->last_success = now; + /* Failure is not success. No catch-up burst and no retry of an old frame. */ + uint32_t delay = s->interval ? s->interval : (result == ESP_OK ? 0 : 1000); + s->next_attempt = after_ms(now, delay); + } else s_stats.stale++; + if (result == ESP_OK) s_stats.success++; else s_stats.failure++; + s_outstanding--; + wake_locked(); + portEXIT_CRITICAL(&s_lock); } - -/* 定时器回调:CPU 统计 */ -static void cpu_stats_timer_callback(void *arg) +static bool reserve(subscription_t *s, target_t *t) { - // 直接调用 API 并广播 - ts_api_result_t result = {0}; - esp_err_t ret = ts_api_call("system.cpu", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - ts_ws_broadcast_to_topic("system.cpu", result.data); - } + if (s_sequence == UINT64_MAX) { s_state=STOPPING; wake_locked(); return false; } /* fail closed, never reuse IDs */ + s->pending = ++s_sequence; + *t = (target_t){s->peer,s->revision,s->pending,s->topic}; + s_outstanding++; + return true; } - -/* 定时器回调:Dashboard 聚合数据 */ -static void dashboard_timer_callback(void *arg) +static void submit(target_t t, ts_ws_message_t *m) { - // 创建聚合 JSON 对象 - cJSON *dashboard = cJSON_CreateObject(); - if (!dashboard) { - TS_LOGE(TAG, "Failed to create dashboard JSON"); - return; - } - - ts_api_result_t result = {0}; - esp_err_t ret; - - // 1. CPU 统计(高频数据) - ret = ts_api_call("system.cpu", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "cpu", result.data); - result.data = NULL; // 所有权转移,防止重复释放 - } - - // 2. 内存信息 - ret = ts_api_call("system.memory", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "memory", result.data); - result.data = NULL; - } - - // 3. 系统信息(uptime 等) - ret = ts_api_call("system.info", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "info", result.data); - result.data = NULL; - } - - // 4. 网络状态 - ret = ts_api_call("network.status", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "network", result.data); - result.data = NULL; - } - - // 5. 电源状态 - ret = ts_api_call("power.status", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "power", result.data); - result.data = NULL; - } - - // 6. 风扇状态 - ret = ts_api_call("fan.status", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "fan", result.data); - result.data = NULL; - } - - // 7. 服务列表 - ret = ts_api_call("service.list", NULL, &result); - if (ret == ESP_OK && result.code == 0 && result.data) { - cJSON_AddItemToObject(dashboard, "services", result.data); - result.data = NULL; - } - - // 广播聚合数据(会复制一次数据) - ts_ws_broadcast_to_topic("system.dashboard", dashboard); - - // 释放聚合对象(包含所有子对象) - cJSON_Delete(dashboard); + esp_err_t ret = ESP_ERR_NO_MEM; + if (m && delivery_valid(t.revision,t.delivery)) + ret = ts_ws_transport_submit(t.peer,m,t.revision,t.delivery,delivery_valid,delivery_done); + if (ret != ESP_OK) delivery_done(t.revision,t.delivery,ret); + else { portENTER_CRITICAL(&s_lock); s_stats.queued++; portEXIT_CRITICAL(&s_lock); } } - -/*===========================================================================*/ -/* 公共 API */ -/*===========================================================================*/ - -esp_err_t ts_ws_subscriptions_init(void) +static bool metric_needed(target_t *targets, unsigned n, unsigned metric) { - if (s_subs_mutex) { - return ESP_OK; // 已初始化 - } - - // 创建互斥锁 - s_subs_mutex = xSemaphoreCreateMutex(); - if (!s_subs_mutex) { - TS_LOGE(TAG, "Failed to create mutex"); - return ESP_ERR_NO_MEM; - } - - // 清空订阅数组 - memset(s_subscriptions, 0, sizeof(s_subscriptions)); - - // 创建定时器(5秒间隔推送系统信息) - esp_timer_create_args_t timer_args = { - .callback = system_info_timer_callback, - .name = "system_info_timer" - }; - esp_err_t ret = esp_timer_create(&timer_args, &s_system_info_timer); - if (ret != ESP_OK) { - TS_LOGE(TAG, "Failed to create system info timer: %s", esp_err_to_name(ret)); - vSemaphoreDelete(s_subs_mutex); - s_subs_mutex = NULL; - return ret; - } - - // 创建 CPU 统计定时器(1秒间隔) - esp_timer_create_args_t cpu_timer_args = { - .callback = cpu_stats_timer_callback, - .name = "cpu_stats_timer" - }; - ret = esp_timer_create(&cpu_timer_args, &s_cpu_stats_timer); - if (ret != ESP_OK) { - TS_LOGE(TAG, "Failed to create CPU stats timer: %s", esp_err_to_name(ret)); - esp_timer_delete(s_system_info_timer); - vSemaphoreDelete(s_subs_mutex); - s_subs_mutex = NULL; - return ret; - } - - // 创建 Dashboard 聚合定时器(1秒间隔) - esp_timer_create_args_t dashboard_timer_args = { - .callback = dashboard_timer_callback, - .name = "dashboard_timer" - }; - ret = esp_timer_create(&dashboard_timer_args, &s_dashboard_timer); - if (ret != ESP_OK) { - TS_LOGE(TAG, "Failed to create dashboard timer: %s", esp_err_to_name(ret)); - esp_timer_delete(s_cpu_stats_timer); - esp_timer_delete(s_system_info_timer); - vSemaphoreDelete(s_subs_mutex); - s_subs_mutex = NULL; - return ret; - } - - TS_LOGI(TAG, "Subscription manager initialized"); - return ESP_OK; + for (unsigned i=0;ifd = fd; - strncpy(sub->topic, topic, MAX_TOPIC_LEN - 1); - sub->topic[MAX_TOPIC_LEN - 1] = '\0'; - sub->min_interval_ms = mapping->default_min_interval_ms; - sub->last_broadcast_time = 0; - sub->active = true; - - // 从参数中提取自定义间隔 - if (params) { - cJSON *interval = cJSON_GetObjectItem(params, "interval"); - if (cJSON_IsNumber(interval) && interval->valueint > 0) { - sub->min_interval_ms = interval->valueint; - } - } - - // 检查是否需要注册事件处理器(首个订阅该主题的客户端) - int count = count_active_subscriptions(topic); - bool first_subscriber = (count == 1); - - xSemaphoreGive(s_subs_mutex); - - if (first_subscriber) { - // 注册事件处理器 - ts_event_handler_handle_t *handle = NULL; - void (*handler)(const ts_event_t *, void *) = NULL; - - if (strcmp(topic, "system.memory") == 0 || - strcmp(topic, "network.status") == 0 || - strcmp(topic, "power.status") == 0 || - strcmp(topic, "fan.status") == 0 || - strcmp(topic, "service.list") == 0) { - handle = &s_system_event_handle; - handler = system_event_handler; - - // 启动定时器(5秒间隔) - if (s_system_info_timer && !esp_timer_is_active(s_system_info_timer)) { - esp_timer_start_periodic(s_system_info_timer, 5000000); // 5秒 - TS_LOGI(TAG, "Started system data timer (5s interval)"); - } - } else if (strcmp(topic, "system.cpu") == 0) { - // CPU 统计使用独立的 1秒定时器 - if (s_cpu_stats_timer && !esp_timer_is_active(s_cpu_stats_timer)) { - esp_timer_start_periodic(s_cpu_stats_timer, 1000000); // 1秒 - TS_LOGI(TAG, "Started CPU stats timer (1s interval)"); + ts_ws_op_poll(); + ts_ws_transport_flush(); + target_t targets[MAX_SUBSCRIPTIONS]; + ts_ws_reservation_t reserved[8]={0}; + unsigned n=0,capacity; + int64_t now=esp_timer_get_time(); + unsigned first=s_topic_cursor; + for(unsigned turn=0;turn<8;turn++) { + unsigned topic=(first+turn)%8; + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; + unsigned slots[TS_WS_CONNECTIONS], count=0; + uint64_t revisions[TS_WS_CONNECTIONS]; + capacity=ts_ws_transport_capacity(); + portENTER_CRITICAL(&s_lock); + if(s_state==RUNNING) for(unsigned j=0;jactive && sub->topic==topic && !sub->pending && now>=sub->next_attempt) { + peers[count]=sub->peer;slots[count]=i;revisions[count++]=sub->revision; } - } else if (strcmp(topic, "system.dashboard") == 0) { - // Dashboard 聚合订阅使用独立的 1秒定时器 - if (s_dashboard_timer && !esp_timer_is_active(s_dashboard_timer)) { - esp_timer_start_periodic(s_dashboard_timer, 1000000); // 1秒 - TS_LOGI(TAG, "Started dashboard timer (1s interval)"); - } - } else if (strcmp(topic, "device.status") == 0) { - handle = &s_device_event_handle; - handler = device_event_handler; - } else if (strcmp(topic, "ota.progress") == 0) { - handle = &s_ota_event_handle; - handler = ota_event_handler; } - - if (handle && handler) { - esp_err_t ret = ts_event_register( - mapping->event_base, - mapping->event_id, - handler, - NULL, - handle - ); - if (ret == ESP_OK) { - TS_LOGI(TAG, "Registered event handler for topic: %s", topic); - } else { - TS_LOGW(TAG, "Failed to register event handler: %s", esp_err_to_name(ret)); - } + portEXIT_CRITICAL(&s_lock); + if(!count || nowmin_interval_ms); - return ESP_OK; -} - -esp_err_t ts_ws_unsubscribe(int fd, const char *topic) -{ - if (!topic || !s_subs_mutex) return ESP_ERR_INVALID_ARG; - - xSemaphoreTake(s_subs_mutex, portMAX_DELAY); - - // 查找并移除订阅 - bool found = false; - for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { - if (s_subscriptions[i].active && - s_subscriptions[i].fd == fd && - strcmp(s_subscriptions[i].topic, topic) == 0) { - s_subscriptions[i].active = false; - found = true; - break; + /* Resources are owned before pending/API work. Admission and revisions + * may have changed during allocation; such targets retire normally. */ + portENTER_CRITICAL(&s_lock); + for(unsigned j=0;jactive && sub->revision==revisions[j] && !sub->pending && reserve(sub,&targets[n])) n++; + else targets[n++]=(target_t){.topic=topic}; } - } - - // 检查是否需要取消注册事件处理器(最后一个订阅者离开) - int count = count_active_subscriptions(topic); - bool last_subscriber = (count == 0); - - xSemaphoreGive(s_subs_mutex); - - if (last_subscriber) { - // 取消注册事件处理器 - ts_event_handler_handle_t *handle = NULL; - if (strcmp(topic, "system.memory") == 0 || - strcmp(topic, "network.status") == 0 || - strcmp(topic, "power.status") == 0 || - strcmp(topic, "fan.status") == 0 || - strcmp(topic, "service.list") == 0) { - handle = &s_system_event_handle; - - // 检查是否还有其他 system.* 订阅 - int system_subs = count_active_subscriptions("system.memory") + - count_active_subscriptions("network.status") + - count_active_subscriptions("power.status") + - count_active_subscriptions("fan.status") + - count_active_subscriptions("service.list"); - - // 如果所有 system.* topic 都没有订阅了,停止定时器 - if (system_subs == 0 && s_system_info_timer) { - esp_timer_stop(s_system_info_timer); - TS_LOGI(TAG, "Stopped system data timer"); + s_subscription_cursor=(slots[count-1]+1)%MAX_SUBSCRIPTIONS; + portEXIT_CRITICAL(&s_lock); + s_topic_cursor=(topic+1)%8; + } + if(n) { TS_WS_TEST_POINT("snapshot"); collect_batch(targets,n,reserved); } + /* Event FIFO per subscription. A slow target does not hold up other targets. + * Different operation results never overwrite each other. */ + for(unsigned slot=0;slotready) { + for(unsigned j=0;jtargets[j]) { + subscription_t *s=find_revision(e->targets[j]); + if(!s || (s_state!=RUNNING && s_state!=DRAINING)) {e->targets[j]=0;continue;} + bool earlier=false; + for(unsigned k=0;korder) + for(unsigned l=0;lrevision) earlier=true; + if(!earlier && !s->pending && now>=s->next_attempt && ntargets[j]=0; + } } - } else if (strcmp(topic, "system.cpu") == 0) { - // 停止 CPU 统计定时器 - if (s_cpu_stats_timer && count_active_subscriptions("system.cpu") == 0) { - esp_timer_stop(s_cpu_stats_timer); - TS_LOGI(TAG, "Stopped CPU stats timer"); - } - } else if (strcmp(topic, "device.status") == 0) { - handle = &s_device_event_handle; - } else if (strcmp(topic, "ota.progress") == 0) { - handle = &s_ota_event_handle; + bool remaining=false; + for(unsigned j=0;jtargets[j]) remaining=true; + if(!remaining) {release=e->message; e->ready=false; /* held until submits finish */} } - - if (handle && *handle) { - ts_event_unregister(*handle); - *handle = NULL; - TS_LOGI(TAG, "Unregistered event handler for topic: %s", topic); + ts_ws_message_t *m=e->message; + portEXIT_CRITICAL(&s_lock); + for(unsigned j=0;j=portMAX_DELAY) ticks=portMAX_DELAY-1; + return (TickType_t)ticks; +} +static TickType_t next_wait(void) +{ + if(ts_ws_transport_needs_flush()) return wait_ticks((int64_t)ts_ws_transport_retry_ms()*1000); + int64_t now=esp_timer_get_time(), nearest=ts_ws_op_needs_tick()?esp_timer_get_time()+100000:INT64_MAX; + unsigned capacity=ts_ws_message_capacity() ? ts_ws_transport_capacity() : 0; + portENTER_CRITICAL(&s_lock); + for(unsigned i=0;iactive || s->pending) continue; + bool wanted=s->topic<8; + for(unsigned j=0;jrevision) wanted=true; + if(wanted && s->next_attemptnext_attempt; + } + if(nearest==INT64_MAX) s_stats.idle_wait++; + if(!capacity && nearest!=INT64_MAX) {nearest=after_ms(now,1000);s_stats.capacity_wait++;} + portEXIT_CRITICAL(&s_lock); + if(nearest!=INT64_MAX && nearestdata || !event->data_size) return; + /* Parse bounded event bytes, not an assumed NUL terminated buffer. */ + cJSON *data=cJSON_ParseWithLength(event->data,event->data_size); + if(data) {ts_ws_broadcast_to_topic(topics[topic].name,data);cJSON_Delete(data);} +} +esp_err_t ts_ws_subscriptions_init(void) +{ + portENTER_CRITICAL(&s_lock); + if(s_state!=OFF) {esp_err_t ret=s_state==RUNNING?ESP_OK:ESP_ERR_INVALID_STATE;portEXIT_CRITICAL(&s_lock);return ret;} + s_state=STARTING; + portEXIT_CRITICAL(&s_lock); + const ts_event_base_t bases[]={TS_EVENT_BASE_SYSTEM,TS_EVENT_BASE_DEVICE_MON,TS_EVENT_BASE_OTA}; + const int ids[]={TS_EVENT_SYSTEM_INFO_CHANGED,TS_EVENT_DEVICE_STATUS_CHANGED,TS_EVENT_OTA_PROGRESS_UPDATE}; + const unsigned mapping[]={0,8,9}; + esp_err_t ret=ESP_OK; + for(unsigned i=0;i<3;i++) { + ret=ts_event_register(bases[i],ids[i],event_handler,(void*)(uintptr_t)mapping[i],&s_handlers[i]); + if(ret!=ESP_OK) break; + } + if(ret==ESP_OK && xTaskCreate(telemetry_worker,"ws_telemetry",WORKER_STACK,NULL,2,&s_worker)!=pdPASS) ret=ESP_ERR_NO_MEM; + portENTER_CRITICAL(&s_lock);s_state=ret==ESP_OK?RUNNING:STOPPING;wake_locked();portEXIT_CRITICAL(&s_lock); + if(ret!=ESP_OK) {esp_err_t cleanup=ts_ws_subscriptions_deinit();if(cleanup!=ESP_OK)return cleanup;} + return ret; +} +/* Stop telemetry/new subscriptions, but keep result subscriptions and the shared + * sender alive until their producers have finished. Safe to retry. */ +esp_err_t ts_ws_subscriptions_pause(void) +{ + portENTER_CRITICAL(&s_lock); + esp_err_t ret=ESP_OK; + if(s_state==RUNNING) { + s_state=DRAINING; + for(unsigned i=0;i=deadline) return ESP_ERR_TIMEOUT; + vTaskDelay(1); } - - return found ? ESP_OK : ESP_ERR_NOT_FOUND; } - -void ts_ws_client_disconnected(int fd) +esp_err_t ts_ws_subscriptions_deinit(void) { - if (!s_subs_mutex) return; - - xSemaphoreTake(s_subs_mutex, portMAX_DELAY); - - // 移除该客户端的所有订阅 - for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { - if (s_subscriptions[i].active && s_subscriptions[i].fd == fd) { - char topic[MAX_TOPIC_LEN]; - strncpy(topic, s_subscriptions[i].topic, MAX_TOPIC_LEN); - s_subscriptions[i].active = false; - - xSemaphoreGive(s_subs_mutex); - ts_ws_unsubscribe(fd, topic); // 递归调用,处理事件取消注册 - xSemaphoreTake(s_subs_mutex, portMAX_DELAY); + if(ts_event_in_callback() || ts_ws_transport_in_context()) return ESP_ERR_INVALID_STATE; + portENTER_CRITICAL(&s_lock); + if(s_state==OFF) {portEXIT_CRITICAL(&s_lock);return ESP_OK;} + if(s_stop_owner || s_state==STARTING || s_worker==xTaskGetCurrentTaskHandle()) {portEXIT_CRITICAL(&s_lock);return ESP_ERR_INVALID_STATE;} + s_stop_owner=true;s_state=STOPPING; + for(unsigned i=0;i=deadline) {ret=ESP_ERR_TIMEOUT;goto done;} + vTaskDelay(1); + } + for(unsigned i=0;ivaluedouble; + if(!cJSON_IsNumber(p)||!isfinite(v)||v<0||v>UINT32_MAX||floor(v)!=v||(v==0 && id<8)) return ESP_ERR_INVALID_ARG; + interval=(uint32_t)v; + if(id<8 && intervalactive && s->topic==(unsigned)id && ts_ws_peer_equal(s->peer,peer)) {slot=s;break;} + if(!s->active && !slot) slot=s; + } + if(s_state==RUNNING && slot && s_sequence!=UINT64_MAX) { + if(!slot->active || slot->interval!=interval) { + int64_t last=slot->active?slot->last_success:0; + *slot=(subscription_t){.peer=peer,.revision=++s_sequence,.topic=id,.active=true, + .interval=interval,.last_success=last, + .next_attempt=id<8?after_ms(last?last:now,interval):now}; } + ret=ESP_OK;wake_locked(); } - - xSemaphoreGive(s_subs_mutex); - TS_LOGI(TAG, "Cleaned up subscriptions for client %d", fd); + portEXIT_CRITICAL(&s_lock);leave();return ret; +} +esp_err_t ts_ws_unsubscribe(ts_ws_peer_t peer,const char *topic) +{ + int id=topic_id(topic);if(id<0)return ESP_ERR_NOT_FOUND; + if(!enter(true))return ESP_ERR_INVALID_STATE; + esp_err_t ret=ESP_ERR_NOT_FOUND; + portENTER_CRITICAL(&s_lock); + for(unsigned i=0;iused=true;e->order=++s_sequence; + bool any=false; + for(unsigned i=0;itargets[i]=s_subs[i].revision;any=true;} + if(!any) {e->used=false;e=NULL;} + } else s_stats.event_dropped++; + portEXIT_CRITICAL(&s_lock); + if(e) { + ts_ws_message_t *m=ts_ws_message_json(topic,data,esp_timer_get_time()/1000000); + portENTER_CRITICAL(&s_lock); + if(m) {e->message=m;e->ready=true;s_stats.serialized[id]++;wake_locked();} + else {memset(e,0,sizeof(*e));s_stats.event_dropped++;} + portEXIT_CRITICAL(&s_lock); + if(!m) TS_LOGW(TAG,"Topic event rejected: frame budget or allocation exhausted"); + } + leave(); } -void ts_ws_broadcast_to_topic(const char *topic, cJSON *data) +bool ts_ws_subscriptions_in_context(void) { - if (!topic || !data || !s_subs_mutex) return; - - xSemaphoreTake(s_subs_mutex, portMAX_DELAY); - - // 构造 WebSocket 消息 - cJSON *msg = cJSON_CreateObject(); - cJSON_AddStringToObject(msg, "type", "data"); - cJSON_AddStringToObject(msg, "topic", topic); - cJSON_AddItemToObject(msg, "data", cJSON_Duplicate(data, true)); - cJSON_AddNumberToObject(msg, "timestamp", esp_timer_get_time() / 1000000); - - char *json_str = cJSON_PrintUnformatted(msg); - cJSON_Delete(msg); - - if (!json_str) { - xSemaphoreGive(s_subs_mutex); - return; - } - - // 遍历订阅,发送给符合条件的客户端 - int sent_count = 0; - for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { - subscription_t *sub = &s_subscriptions[i]; - if (!sub->active || strcmp(sub->topic, topic) != 0) { - continue; - } - - // 检查去抖动 - if (!should_broadcast(sub)) { - continue; - } - - // 更新时间戳 - sub->last_broadcast_time = esp_timer_get_time(); - - // 发送消息(异步) - // 注意:这里需要从 ts_webui_ws.c 导出发送函数,或使用 broadcast - // 暂时使用 broadcast API - xSemaphoreGive(s_subs_mutex); - ts_webui_broadcast(json_str); // TODO: 优化为只发送给订阅者 - xSemaphoreTake(s_subs_mutex, portMAX_DELAY); - - sent_count++; - } - - xSemaphoreGive(s_subs_mutex); - - if (sent_count > 0) { - TS_LOGD(TAG, "Broadcasted to %d subscribers of '%s'", sent_count, topic); - } - - free(json_str); + TaskHandle_t current=xTaskGetCurrentTaskHandle(); + portENTER_CRITICAL(&s_lock);bool owner=s_worker && s_worker==current;portEXIT_CRITICAL(&s_lock); + return owner; } diff --git a/components/ts_webui/src/ts_ws_transport.c b/components/ts_webui/src/ts_ws_transport.c new file mode 100644 index 0000000..21794f3 --- /dev/null +++ b/components/ts_webui/src/ts_ws_transport.c @@ -0,0 +1,658 @@ +#include "ts_ws_transport.h" +#include "esp_timer.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include +#include + +/* Stable control storage: no caller can race destruction of a mutex. No I/O, + * allocation, JSON operation or completion callback runs under this spinlock. */ +static portMUX_TYPE s_lock = portMUX_INITIALIZER_UNLOCKED; +static uint64_t s_sequence; +static struct { + httpd_handle_t handle; + uint64_t epoch; + bool stopping, barrier_requested, quiesced, work_busy; + unsigned outstanding; + int64_t retry_at; + TaskHandle_t owner; + ts_ws_closed_t closed; +} s_server; +static ts_ws_peer_t s_peers[TS_WS_CONNECTIONS]; +static int s_log_levels[TS_WS_CONNECTIONS]; +static uint64_t s_log_revisions[TS_WS_CONNECTIONS]; +typedef enum {MSG_ORDINARY, MSG_TOPIC, MSG_RESULT, MSG_POWER, MSG_POWER_TICK} message_kind_t; +struct ts_ws_message { unsigned refs; char *text; size_t len, capacity; message_kind_t kind; }; +static char s_power_payloads[TS_WS_POWER_SLOTS][TS_WS_POWER_BYTES]; +static unsigned s_power_bytes; +static ts_ws_transport_stats_t s_tx_stats; +static ts_ws_message_t s_messages[TS_WS_ALL_MESSAGE_SLOTS]; +typedef enum {TX_FREE, TX_RESERVED, TX_PREPARED, TX_QUEUED, TX_EXECUTING, TX_DONE, TX_CANCELED} tx_state_t; +typedef struct { + unsigned refs, retries; + tx_state_t state; + uint64_t order; + ts_ws_peer_t peer; + ts_ws_message_t *message; + uint64_t revision, delivery; + ts_ws_delivery_check_t check; + ts_ws_delivery_done_t done; +} delivery_t; +static delivery_t s_deliveries[TS_WS_ALL_TX_SLOTS]; +static uint64_t s_delivery_order; +extern void ts_ws_subscriptions_wake(void); + +bool ts_ws_peer_equal(ts_ws_peer_t a, ts_ws_peer_t b) +{ + return a.server == b.server && a.epoch == b.epoch && + a.fd == b.fd && a.connection == b.connection; +} +static bool peer_valid(ts_ws_peer_t peer) +{ + if (s_server.handle != peer.server || s_server.epoch != peer.epoch) + return false; + for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) + if (s_peers[i].connection && ts_ws_peer_equal(s_peers[i], peer)) return true; + return false; +} +bool ts_ws_transport_in_context(void) +{ + portENTER_CRITICAL(&s_lock); + bool same = s_server.owner && s_server.owner == xTaskGetCurrentTaskHandle(); + portEXIT_CRITICAL(&s_lock); + return same; +} +esp_err_t ts_ws_transport_start(httpd_handle_t server, ts_ws_closed_t closed) +{ + if (!server) return ESP_ERR_INVALID_ARG; + portENTER_CRITICAL(&s_lock); + esp_err_t ret = ESP_ERR_INVALID_STATE; + if (!s_server.handle && s_sequence != UINT64_MAX) { + s_server.handle = server; + s_server.epoch = ++s_sequence; + s_server.closed = closed; + s_server.stopping = false; + ret = ESP_OK; + } + portEXIT_CRITICAL(&s_lock); + return ret; +} +bool ts_ws_peer_get(httpd_handle_t server, int fd, ts_ws_peer_t *peer) +{ + bool found = false; + portENTER_CRITICAL(&s_lock); + for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) { + if (s_peers[i].connection && s_peers[i].server == server && s_peers[i].fd == fd) { + *peer = s_peers[i]; found = true; break; + } + } + portEXIT_CRITICAL(&s_lock); + return found; +} +void ts_ws_peer_close(ts_ws_peer_t peer) +{ + ts_ws_closed_t closed = NULL; + portENTER_CRITICAL(&s_lock); + for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) { + if (s_peers[i].connection && ts_ws_peer_equal(s_peers[i], peer)) { + s_peers[i].connection = 0; + closed = s_server.closed; + break; + } + } + portEXIT_CRITICAL(&s_lock); + if (closed) closed(peer); +} +static void session_free(void *ctx) +{ + ts_ws_peer_t *peer = ctx; + ts_ws_peer_close(*peer); + free(peer); +} +esp_err_t ts_ws_peer_open(httpd_req_t *req, ts_ws_peer_t *peer) +{ + /* No authentication / TLS context is replaced. Current /ws owns no context. */ + if (req->sess_ctx) return ESP_ERR_INVALID_STATE; + ts_ws_peer_t *ctx = malloc(sizeof(*ctx)); + if (!ctx) return ESP_ERR_NO_MEM; + esp_err_t ret = ESP_ERR_NO_MEM; + portENTER_CRITICAL(&s_lock); + s_server.owner = xTaskGetCurrentTaskHandle(); + if (!s_server.stopping && req->handle == s_server.handle && s_sequence != UINT64_MAX) { + for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) if (!s_peers[i].connection) { + *ctx = (ts_ws_peer_t){req->handle, s_server.epoch, ++s_sequence, httpd_req_to_sockfd(req)}; + s_peers[i] = *ctx; s_log_levels[i] = -1; s_log_revisions[i] = 0; *peer = *ctx; ret = ESP_OK; break; + } + } + portEXIT_CRITICAL(&s_lock); + if (ret != ESP_OK) { free(ctx); return ret; } + req->sess_ctx = ctx; + req->free_ctx = session_free; /* RST, LRU and httpd_stop also release this. */ + return ESP_OK; +} +static ts_ws_message_t *message_alloc(size_t capacity, message_kind_t kind) +{ + if(kind>=MSG_POWER && capacity>TS_WS_POWER_BYTES)return NULL; + ts_ws_message_t *m = NULL; + portENTER_CRITICAL(&s_lock); + unsigned begin=kind>=MSG_POWER ? TS_WS_MESSAGE_SLOTS+2+(kind==MSG_POWER_TICK?TS_WS_POWER_TRANSITIONS:0) : kind==MSG_RESULT ? TS_WS_MESSAGE_SLOTS : kind==MSG_TOPIC ? 0 : TS_WS_MESSAGE_SLOTS-2; + unsigned end=kind==MSG_POWER_TICK ? TS_WS_ALL_MESSAGE_SLOTS : kind==MSG_POWER ? TS_WS_ALL_MESSAGE_SLOTS-1 : kind==MSG_RESULT ? TS_WS_MESSAGE_SLOTS+2 : kind==MSG_TOPIC ? TS_WS_MESSAGE_SLOTS-2 : TS_WS_MESSAGE_SLOTS; + size_t used=kind>=MSG_POWER ? s_power_bytes : s_tx_stats.bytes-s_power_bytes; + size_t limit=kind>=MSG_POWER ? TS_WS_POWER_BUDGET : TS_WS_TOTAL_BYTES-TS_WS_POWER_BUDGET; + for (unsigned i=begin; capacity <= limit-used && irefs = 1; m->capacity = capacity; m->kind=kind; + if(kind>=MSG_POWER)s_power_bytes+=capacity; + s_tx_stats.bytes += capacity; + if(s_tx_stats.bytes > s_tx_stats.bytes_high) s_tx_stats.bytes_high=s_tx_stats.bytes; + break; + } + portEXIT_CRITICAL(&s_lock); + if (m) { + m->text = kind>=MSG_POWER ? s_power_payloads[m-s_messages-TS_WS_MESSAGE_SLOTS-2] : malloc(capacity); + if (!m->text) { + portENTER_CRITICAL(&s_lock);s_tx_stats.rejected++;portEXIT_CRITICAL(&s_lock); + ts_ws_message_release(m);return NULL; + } + } else { + portENTER_CRITICAL(&s_lock);s_tx_stats.rejected++;portEXIT_CRITICAL(&s_lock); + } + return m; +} +void ts_ws_message_release(ts_ws_message_t *m) +{ + if (!m) return; + char *text = NULL; + bool reclaim = false; + portENTER_CRITICAL(&s_lock); + if (--m->refs == 0) { + /* Keep this slot and its byte reservation until free has completed. */ + m->refs = 1; + text = m->text; + reclaim = true; + } + portEXIT_CRITICAL(&s_lock); + if (!reclaim) return; + if(m->kindkind>=MSG_POWER)s_power_bytes-=m->capacity; + m->text = NULL; + m->len = 0; + s_tx_stats.bytes -= m->capacity; + m->refs = 0; + portEXIT_CRITICAL(&s_lock); +} + +ts_ws_message_t *ts_ws_message_text(const char *text, size_t len) +{ + if (!text || len >= TS_WS_LEGACY_BYTES) return NULL; + ts_ws_message_t *m = message_alloc(len + 1, false); + if (m) { memcpy(m->text, text, len); m->text[len] = 0; m->len = len; } + return m; +} +ts_ws_message_t *ts_ws_message_json(const char *topic, const cJSON *data, int64_t timestamp) +{ + ts_ws_message_t *m = message_alloc(TS_WS_FRAME_BYTES, true); + if (!m) return NULL; + cJSON *root = cJSON_CreateObject(); + /* Reference is local to this call; bounded print copies before return. */ + bool ok = root && cJSON_AddStringToObject(root, "type", "data") && + cJSON_AddStringToObject(root, "topic", topic) && + cJSON_AddNumberToObject(root, "timestamp", timestamp) && + ts_ws_json_reference(root, "data", (cJSON *)data) && + cJSON_PrintPreallocated(root, m->text, TS_WS_FRAME_BYTES, false); + cJSON_Delete(root); + if (!ok) { ts_ws_message_release(m); return NULL; } + m->len = strlen(m->text); + return m; +} +unsigned ts_ws_transport_capacity(void) +{ + unsigned n = 0; + portENTER_CRITICAL(&s_lock); + if (!s_server.stopping && s_server.handle) + for (unsigned i = 0; i < TS_WS_TOPIC_TX_SLOTS; ++i) n += !s_deliveries[i].refs; + portEXIT_CRITICAL(&s_lock); + return n; +} +static void delivery_release(delivery_t *d) +{ + ts_ws_message_t *m = NULL; + portENTER_CRITICAL(&s_lock); + if (--d->refs == 0) { + m = d->message; + d->state=TX_FREE; + s_server.outstanding--; + s_tx_stats.jobs--; + } + portEXIT_CRITICAL(&s_lock); + ts_ws_message_release(m); +} +/* Exactly one settlement for every accepted work reference, including stale + * targets and queue rejection. Class is owned by the message, never by done. */ +static void settle(delivery_t *d, esp_err_t result) +{ + portENTER_CRITICAL(&s_lock); + s_tx_stats.settled++; + bool power=d->message->kind>=MSG_POWER; + if(power){s_tx_stats.power_settled++;if(result!=ESP_OK)s_tx_stats.power_failed++;} + portEXIT_CRITICAL(&s_lock); + if(d->message->kind>=MSG_RESULT && result!=ESP_OK)ESP_LOGW("ws_tx","Critical notification target failed: class=%d fd=%d result=%d",d->message->kind,d->peer.fd,result); + if(d->done)d->done(d->revision,d->delivery,result); +} +static void deliver(void *arg) +{ + delivery_t *d = arg; + portENTER_CRITICAL(&s_lock); + s_server.owner = xTaskGetCurrentTaskHandle(); + d->state=TX_EXECUTING; + bool valid = peer_valid(d->peer); + portEXIT_CRITICAL(&s_lock); + esp_err_t ret = ESP_ERR_INVALID_STATE; + /* HTTPD session destruction/handshake/unsubscribe and this send are ordered + * on this same task. The stop owner keeps the server alive until refs drain. */ + if (valid && (!d->check || d->check(d->revision, d->delivery)) && + httpd_ws_get_fd_info(d->peer.server, d->peer.fd) == HTTPD_WS_CLIENT_WEBSOCKET) { + httpd_ws_frame_t frame = {.type = HTTPD_WS_TYPE_TEXT, + .payload = (uint8_t *)d->message->text, .len = d->message->len}; + int64_t start = esp_timer_get_time(); + ret = httpd_ws_send_frame_async(d->peer.server, d->peer.fd, &frame); + int64_t elapsed = esp_timer_get_time() - start; + portENTER_CRITICAL(&s_lock); + s_tx_stats.attempts++; + if(ret==ESP_OK) s_tx_stats.success++; else s_tx_stats.failed++; + if(elapsed>s_tx_stats.max_send_us) s_tx_stats.max_send_us=elapsed; + portEXIT_CRITICAL(&s_lock); + if (ret != ESP_OK) { + /* Owner context: invalidate this socket without taking over close() + * ownership. HTTPD will observe EOF and invoke the session hook. */ + shutdown(d->peer.fd, SHUT_RDWR); + ts_ws_peer_close(d->peer); + } + } else { + portENTER_CRITICAL(&s_lock); s_tx_stats.stale++; portEXIT_CRITICAL(&s_lock); + } + TS_WS_TEST_POINT("sent"); + settle(d,ret); + portENTER_CRITICAL(&s_lock); + d->state=TX_DONE; + s_server.work_busy=false; + portEXIT_CRITICAL(&s_lock); + delivery_release(d); + ts_ws_subscriptions_wake(); +} +/* One SDK control work item at a time. Accepted descriptors stay in our bounded + * FIFO, not the six-entry lwIP UDP control mailbox. Completion only wakes the + * telemetry worker; it never recursively queues another network operation. */ +static esp_err_t publish_delivery(delivery_t *d) +{ + esp_err_t ret=httpd_queue_work(d->peer.server,deliver,d); + portENTER_CRITICAL(&s_lock); + bool retry=ret!=ESP_OK && d->message->kind>=MSG_RESULT && ++d->retriesstate=retry?TX_PREPARED:TX_CANCELED; + if(retry)s_server.retry_at=esp_timer_get_time()+100000; + } + portEXIT_CRITICAL(&s_lock); + if(ret!=ESP_OK){ + if(!retry) { + settle(d,ret); + delivery_release(d); /* failed ordinary work reference */ + } + /* A failure callback may enqueue its reserved terminal. Keep the + * executor busy until settlement ends to avoid recursive queue failures. */ + portENTER_CRITICAL(&s_lock);s_server.work_busy=false;portEXIT_CRITICAL(&s_lock); + ts_ws_subscriptions_wake(); + } + delivery_release(d); /* publication reference, may outlive the callback */ + return ret; +} +void ts_ws_transport_flush(void) +{ + delivery_t *next=NULL; + portENTER_CRITICAL(&s_lock); + if(s_server.handle && !s_server.work_busy && esp_timer_get_time()>=s_server.retry_at) { + for(unsigned i=0;iorder))next=&s_deliveries[i]; + if(next){next->state=TX_QUEUED;next->refs++;s_server.work_busy=true;} + } + portEXIT_CRITICAL(&s_lock); + if(next)publish_delivery(next); +} +bool ts_ws_transport_needs_flush(void) +{ + bool ready=false; + portENTER_CRITICAL(&s_lock); + if(s_server.handle && !s_server.work_busy) + for(unsigned i=0;istate==TX_PREPARED && (!topics_only || istate=TX_CANCELED;s_tx_stats.stale++;} /* take its existing work reference */ + portEXIT_CRITICAL(&s_lock); + if(cancel){settle(d,ESP_ERR_INVALID_STATE);delivery_release(d);} + } +} +void ts_ws_transport_cancel_topics(void){cancel_ready(true);} +esp_err_t ts_ws_transport_submit(ts_ws_peer_t peer, ts_ws_message_t *message, + uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done) +{ + if(!message || message->kind>MSG_TOPIC)return ESP_ERR_INVALID_ARG; + delivery_t *d=NULL; + portENTER_CRITICAL(&s_lock); + if(!s_server.stopping && peer_valid(peer) && s_delivery_order!=UINT64_MAX) + for(unsigned i=message->kind==MSG_TOPIC?0:TS_WS_TOPIC_TX_SLOTS;i<(message->kind==MSG_TOPIC?TS_WS_TOPIC_TX_SLOTS:TS_WS_TX_SLOTS);i++)if(!s_deliveries[i].refs){ + d=&s_deliveries[i]; + *d=(delivery_t){.refs=2,.state=TX_PREPARED,.order=++s_delivery_order,.peer=peer, + .message=message,.revision=revision,.delivery=delivery,.check=check,.done=done}; + message->refs++;s_server.outstanding++;s_tx_stats.jobs++; + if(s_tx_stats.jobs>s_tx_stats.jobs_high)s_tx_stats.jobs_high=s_tx_stats.jobs; + break; + } + if(!d)s_tx_stats.rejected++; + portEXIT_CRITICAL(&s_lock); + if(!d)return ESP_ERR_NO_MEM; + /* Accepted into the local FIFO. Queue/send failures are settled through done, + * exactly once. The producer reference prevents early completion reuse. */ + ts_ws_transport_flush(); + TS_WS_TEST_POINT("B05"); /* done may have returned; producer ref still held */ + delivery_release(d); + ts_ws_subscriptions_wake(); + return ESP_OK; +} +esp_err_t ts_ws_transport_send(httpd_handle_t server, int fd, const httpd_ws_frame_t *frame) +{ + ts_ws_peer_t peer; + if (!ts_ws_peer_get(server, fd, &peer)) return ESP_ERR_INVALID_STATE; + if(ts_ws_transport_in_context()) { + /* Current HTTP request owns the session until it returns; HTTPD stop + * waits for that request. Keep synchronous terminal takeover ordering. */ + return httpd_ws_send_frame_async(server,fd,(httpd_ws_frame_t *)frame); + } + ts_ws_message_t *m = ts_ws_message_text((const char *)frame->payload, frame->len); + if (!m) return ESP_ERR_NO_MEM; + esp_err_t ret = ts_ws_transport_submit(peer, m, 0, 0, NULL, NULL); + ts_ws_message_release(m); + return ret; +} +esp_err_t ts_ws_transport_stop(httpd_handle_t server, uint32_t timeout_ms) +{ + if (ts_ws_transport_in_context()) return ESP_ERR_INVALID_STATE; + int64_t now = esp_timer_get_time(), delta = (int64_t)timeout_ms * 1000; + int64_t deadline = now > INT64_MAX - delta ? INT64_MAX : now + delta; + for (;;) { + portENTER_CRITICAL(&s_lock); + if (!s_server.handle) { portEXIT_CRITICAL(&s_lock); return ESP_OK; } + if (server != s_server.handle) { portEXIT_CRITICAL(&s_lock); return ESP_ERR_INVALID_ARG; } + s_server.stopping = true; + portEXIT_CRITICAL(&s_lock); + ts_ws_transport_flush(); /* drain accepted results; never cancel them on normal stop */ + portENTER_CRITICAL(&s_lock); + unsigned outstanding=s_server.outstanding; + portEXIT_CRITICAL(&s_lock); + if (!outstanding) return ESP_OK; + if (esp_timer_get_time() >= deadline) return ESP_ERR_TIMEOUT; + vTaskDelay(1); + } +} +/* Called only after actual HTTPD stop has freed all sessions. */ +void ts_ws_transport_stopped(httpd_handle_t server) +{ + portENTER_CRITICAL(&s_lock); + if (s_server.handle == server && s_server.stopping && !s_server.outstanding) { + memset(&s_server, 0, sizeof(s_server)); + memset(s_peers, 0, sizeof(s_peers)); + } + portEXIT_CRITICAL(&s_lock); +} + +static bool log_allowed(uint64_t revision, uint64_t level) +{ + bool allowed=false; + portENTER_CRITICAL(&s_lock); + for(unsigned i=0;i=0 && level<=(unsigned)s_log_levels[i]) allowed=true; + portEXIT_CRITICAL(&s_lock); + return allowed; +} +static esp_err_t broadcast_filtered(const httpd_ws_frame_t *frame, int level) +{ + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; + uint64_t revisions[TS_WS_CONNECTIONS]; + unsigned n=0; + portENTER_CRITICAL(&s_lock); + if(!s_server.stopping) for(unsigned i=0;ipayload,frame->len); + if(!m) return ESP_ERR_NO_MEM; + esp_err_t ret=ESP_OK; + for(unsigned i=0;i= (int64_t)timeout_ms*1000)return ESP_ERR_TIMEOUT; + vTaskDelay(1); + } +} + +unsigned ts_ws_peer_snapshot(ts_ws_peer_t *peers, unsigned capacity) +{ + unsigned n=0; + portENTER_CRITICAL(&s_lock); + if(!s_server.stopping) for(unsigned i=0;iTS_WS_RESERVATION_TARGETS || !bytes || bytes>TS_WS_LEGACY_BYTES) return ESP_ERR_INVALID_ARG; + *r=(ts_ws_reservation_t){0}; + ts_ws_message_t *m=message_alloc(bytes,kind); + if(!m) return ESP_ERR_NO_MEM; + unsigned begin=kind>=MSG_POWER ? TS_WS_RESULT_TX_END+(kind==MSG_POWER_TICK?TS_WS_POWER_TRANSITIONS*TS_WS_CONNECTIONS:0) : kind==MSG_RESULT?TS_WS_TX_SLOTS:0; + unsigned end=kind==MSG_POWER_TICK?TS_WS_ALL_TX_SLOTS:kind==MSG_POWER?TS_WS_ALL_TX_SLOTS-TS_WS_CONNECTIONS:kind==MSG_RESULT?TS_WS_RESULT_TX_END:TS_WS_TOPIC_TX_SLOTS; + portENTER_CRITICAL(&s_lock); + bool valid=!s_server.stopping && s_server.handle; + for(unsigned i=0;peers && i=count) { + for(unsigned i=begin,j=0;islots[j++]=i;m->refs++;s_server.outstanding++;s_tx_stats.jobs++; + } + r->count=count;r->message=m; + if(s_tx_stats.jobs>s_tx_stats.jobs_high)s_tx_stats.jobs_high=s_tx_stats.jobs; + } + portEXIT_CRITICAL(&s_lock); + if(!r->message){ts_ws_message_release(m);return valid?ESP_ERR_NO_MEM:ESP_ERR_INVALID_STATE;} + return ESP_OK; +} +esp_err_t ts_ws_reserve(const ts_ws_peer_t *peers,unsigned count,bool result,size_t bytes,ts_ws_reservation_t *r) +{ + return reserve_kind(peers,count,result?MSG_RESULT:MSG_TOPIC,bytes,r); +} +void ts_ws_reservation_release(ts_ws_reservation_t *r) +{ + if(!r || !r->message)return; + for(unsigned i=0;icount;i++)if(r->slots[i]>=0) delivery_release(&s_deliveries[r->slots[i]]); + ts_ws_message_release(r->message); + *r=(ts_ws_reservation_t){0}; + ts_ws_subscriptions_wake(); +} +bool ts_ws_reserved_json(ts_ws_reservation_t *r,const char *topic,const cJSON *data,int64_t timestamp) +{ + if(!r->message)return false; + cJSON *root=cJSON_CreateObject(); + bool ok=root && cJSON_AddStringToObject(root,"type","data") && cJSON_AddStringToObject(root,"topic",topic) && + cJSON_AddNumberToObject(root,"timestamp",timestamp) && ts_ws_json_reference(root,"data",data) && + cJSON_PrintPreallocated(root,r->message->text,r->message->capacity,false); + cJSON_Delete(root); + if(ok)r->message->len=strlen(r->message->text); + return ok; +} +esp_err_t ts_ws_reserved_text(ts_ws_reservation_t *r,const char *text) +{ + if(!r || !r->message || !text)return ESP_ERR_INVALID_ARG; + size_t n=strlen(text); + if(n>=r->message->capacity)return ESP_ERR_INVALID_SIZE; + memcpy(r->message->text,text,n+1);r->message->len=n; + return ESP_OK; +} +esp_err_t ts_ws_reserved_submit(ts_ws_reservation_t *r,unsigned index,uint64_t revision, + uint64_t delivery,ts_ws_delivery_check_t check,ts_ws_delivery_done_t done) +{ + if(!r || !r->message || index>=r->count || r->slots[index]<0)return ESP_ERR_INVALID_ARG; + delivery_t *d=&s_deliveries[r->slots[index]]; + portENTER_CRITICAL(&s_lock); + bool valid=!s_server.stopping && peer_valid(d->peer) && s_delivery_order!=UINT64_MAX; + if(valid) { + d->revision=revision;d->delivery=delivery;d->check=check;d->done=done; + d->order=++s_delivery_order;d->state=TX_PREPARED;d->refs++; /* work + reservation */ + } + portEXIT_CRITICAL(&s_lock); + if(!valid)return ESP_ERR_INVALID_STATE; + r->slots[index]=-1; + ts_ws_transport_flush();delivery_release(d);ts_ws_subscriptions_wake(); + return ESP_OK; +} + +esp_err_t ts_ws_result_reserve(size_t bytes,ts_ws_reservation_t *r) +{ + return ts_ws_reserve(NULL,TS_WS_CONNECTIONS,true,bytes,r); +} +esp_err_t ts_ws_result_broadcast(ts_ws_reservation_t *r,const char *text) +{ + esp_err_t ret=ts_ws_reserved_text(r,text); + if(ret!=ESP_OK)return ret; + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; + unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); + return ts_ws_result_publish(r,peers,n); +} +esp_err_t ts_ws_result_publish(ts_ws_reservation_t *r,const ts_ws_peer_t *peers,unsigned n) +{ + esp_err_t ret=ESP_OK; + for(unsigned i=0;i=r->count || r->slots[i]<0)return ESP_ERR_INVALID_STATE; + portENTER_CRITICAL(&s_lock);s_deliveries[r->slots[i]].peer=peers[i];portEXIT_CRITICAL(&s_lock); + esp_err_t result=ts_ws_reserved_submit(r,i,0,0,NULL,NULL); + if(result!=ESP_OK)ret=result; + } + return ret; +} + +uint32_t ts_ws_transport_retry_ms(void) +{ + portENTER_CRITICAL(&s_lock); + int64_t delta=s_server.retry_at-esp_timer_get_time(); + portEXIT_CRITICAL(&s_lock); + return delta>0 ? (uint32_t)((delta+999)/1000) : 0; +} + +esp_err_t ts_ws_power_reserve(bool tick,ts_ws_reservation_t *r) +{ + *r=(ts_ws_reservation_t){0}; + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; + unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); + if(!n)return ESP_OK; + esp_err_t ret=reserve_kind(peers,n,tick?MSG_POWER_TICK:MSG_POWER,TS_WS_POWER_BYTES,r); + portENTER_CRITICAL(&s_lock); + if(ret==ESP_OK)s_tx_stats.power_accepted++;else s_tx_stats.power_rejected++; + portEXIT_CRITICAL(&s_lock); + return ret; +} +esp_err_t ts_ws_power_publish(ts_ws_reservation_t *r,const char *text) +{ + if(!r->message)return ESP_OK; /* no recipients at admission */ + esp_err_t ret=ts_ws_reserved_text(r,text); + if(ret!=ESP_OK)return ret; + for(unsigned i=0;icount;i++) { + esp_err_t result=ts_ws_reserved_submit(r,i,0,0,NULL,NULL); + if(result!=ESP_OK){ret=result;portENTER_CRITICAL(&s_lock);s_tx_stats.power_failed++;portEXIT_CRITICAL(&s_lock);} + } + return ret; +} + +esp_err_t ts_ws_reserved_target(ts_ws_reservation_t *r,unsigned index,ts_ws_peer_t peer, + uint64_t revision,uint64_t delivery,ts_ws_delivery_done_t done) +{ + if(!r || index>=r->count || r->slots[index]<0)return ESP_ERR_INVALID_ARG; + portENTER_CRITICAL(&s_lock);s_deliveries[r->slots[index]].peer=peer;portEXIT_CRITICAL(&s_lock); + return ts_ws_reserved_submit(r,index,revision,delivery,NULL,done); +} diff --git a/components/ts_webui/web/index.html b/components/ts_webui/web/index.html index 78583e4..eea293c 100644 --- a/components/ts_webui/web/index.html +++ b/components/ts_webui/web/index.html @@ -41,9 +41,9 @@ .modal-content{background:var(--bg-card);border-radius:var(--radius-lg);max-width:600px;width:95%;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg)} - - - + + + @@ -77,7 +77,7 @@ 安全
-
+
未登录
@@ -247,38 +247,46 @@

电压保护设置

- - - - - + + + + + diff --git a/components/ts_webui/web/js/api.js b/components/ts_webui/web/js/api.js index 79dd483..db9f9e4 100644 --- a/components/ts_webui/web/js/api.js +++ b/components/ts_webui/web/js/api.js @@ -37,6 +37,55 @@ function getApiUrl(endpoint) { return `${API_BASE}${endpoint}`; } +// Keep REST business failures as returned envelopes. Strict consumers opt in below. +function apiErrorReason(result) { + for (const value of [result?.rawMessage, result?.error, result?.message]) { + if (typeof value === 'string' && value.trim()) return value.trim(); + } + return ''; +} +function apiErrorMessage(result, operation = '') { + const raw = apiErrorReason(result); + const reasons = { + 'Invalid credentials': 'credentials', 'Invalid username or password': 'credentials', 'Old password is incorrect': 'oldPassword', + 'SD card not mounted': 'sdUnavailable', 'SD card already mounted': 'sdMounted', + 'File not found': 'fileMissing', 'Directory not found': 'directoryMissing', + 'Source file not found': 'fileMissing', 'Cannot delete root directory': 'rootDirectory', + 'Failed to stat file': 'fileInfo', 'Memory allocation failed': 'memory', + 'Request timeout': 'timeout', 'Failed to fetch': 'connection' + }; + const codes = ['unknownError', 'invalidInput', 'notFound', 'permission', 'busy', 'timeout', + 'memory', 'internal', 'unsupported', 'hardware', 'connection', 'auth']; + const names = {INVALID_ARG:1, NOT_FOUND:2, NO_PERMISSION:3, BUSY:4, TIMEOUT:5, + NO_MEM:6, INTERNAL:7, NOT_SUPPORTED:8, HARDWARE:9, CONNECTION:10, AUTH:11}; + const code = typeof result?.code === 'number' ? result.code : names[result?.code]; + const key = result?.kind === 'timeout' ? (result.uncertain ? 'resultUnknown' : 'timeout') + : result?.kind === 'network' ? (result.uncertain ? 'resultUnknown' : 'connection') + : result?.kind === 'format' ? (result.uncertain ? 'resultUnknown' : 'invalidResponse') + : reasons[raw] || codes[code] || 'unknownError'; + const message = t('promptRepair.' + key); + // Unknown backend text remains diagnostic detail, not the entire user explanation. + const detail = raw && !reasons[raw] ? '\n' + t('promptRepair.details', {detail: raw}) : ''; + return message + detail; +} +class ApiOperationError extends Error { + constructor(result, operation = '', metadata = {}) { + super(apiErrorMessage({...result, ...metadata}, operation)); + this.name = 'ApiOperationError'; + this.code = result?.code; + this.rawMessage = apiErrorReason(result); + this.operation = operation; + this.httpStatus = result?.httpStatus; + Object.assign(this, metadata); + } +} +function requireApiSuccess(result, operation = '') { + if (!result || result.code !== 0 || (result.httpStatus && result.httpStatus >= 400)) { + throw new ApiOperationError(result, operation); + } + return result; +} + class TianShanAPI { constructor() { // 从 localStorage 恢复 token(注意 key 是 ts_token) @@ -92,14 +141,16 @@ class TianShanAPI { console.debug(`API ${method} ${endpoint}: body size = ${options.body.length} bytes`); } + let httpStatus; try { const response = await fetch(getApiUrl(endpoint), options); - clearTimeout(timeoutId); + httpStatus = response.status; const text = await response.text(); let json; try { json = JSON.parse(text); } catch (parseErr) { + if (!response.ok) throw new ApiOperationError({error: text}, endpoint, {httpStatus: response.status}); // 响应可能被 WebSocket 等数据污染(如 ~{"type"...),尝试从某处解析出带 code 的 API 格式 if (parseErr instanceof SyntaxError && text) { let idx = 0; @@ -120,8 +171,16 @@ class TianShanAPI { } // 返回 JSON 响应,即使是错误码也返回(让调用者决定如何处理) - if (!response.ok && !json.code) { - throw new Error(json.message || json.error || 'Request failed'); + if (!response.ok) throw new ApiOperationError(json, endpoint, {httpStatus: response.status}); + const logoutResponse = endpoint === '/auth/logout' && method === 'POST'; + if (!json || typeof json !== 'object' || Array.isArray(json) || + (logoutResponse ? json.success !== true : !('code' in json))) { + throw new ApiOperationError({}, endpoint, {kind: 'format', uncertain: method !== 'GET', httpStatus: response.status}); + } + json.httpStatus = response.status; + if (!logoutResponse && json.code !== 0) { + json.rawMessage = apiErrorReason(json); + json.message = apiErrorMessage(json, endpoint); } const isAuthEndpoint = endpoint === '/auth/login' || endpoint === '/auth/logout'; @@ -136,13 +195,11 @@ class TianShanAPI { return json; } catch (error) { + if (error instanceof ApiOperationError) throw error; + const kind = controller.signal.aborted ? 'timeout' : error instanceof SyntaxError ? 'format' : 'network'; + throw new ApiOperationError({message: error.message}, endpoint, {kind, uncertain: method !== 'GET', httpStatus}); + } finally { clearTimeout(timeoutId); - if (error.name === 'AbortError') { - console.error(`API Timeout: ${endpoint} (>${timeout}ms)`); - throw new Error('Request timeout'); - } - console.error(`API Error: ${endpoint}`, error); - throw error; } } @@ -186,7 +243,10 @@ class TianShanAPI { async login(username, password) { const result = await this.call('auth.login', { username, password }, 'POST'); - if ((result.success || result.code === 0 || result.code === 'OK') && result.data?.token) { + if (result.code === 0 && (typeof result.data?.token !== 'string' || !result.data.token)) { + throw new ApiOperationError({}, 'auth.login', {kind: 'format'}); + } + if (result.code === 0 && result.data?.token) { this.token = result.data.token; this.username = result.data.username; this.level = result.data.level; @@ -200,15 +260,20 @@ class TianShanAPI { } async logout() { + // request() captures Authorization before local credentials are cleared. + const pending = this.token ? this.call('auth.logout', {token: this.token}, 'POST') : null; + this.clearAuth(); try { - if (this.token) { - await this.call('auth.logout', { token: this.token }, 'POST'); + if (pending) { + await pending; + return {localCleared: true, serverConfirmed: true}; } - } finally { - this.clearAuth(); + return {localCleared: true, serverConfirmed: false}; + } catch (error) { + return {localCleared: true, serverConfirmed: false, error}; } } - + async checkAuthStatus() { if (!this.token) return { valid: false }; const result = await this.call('auth.status', { token: this.token }, 'POST'); @@ -467,7 +532,7 @@ class TianShanAPI { }); if (!response.ok) { const error = await response.json().catch(() => ({ message: 'Download failed' })); - throw new Error(error.message); + throw new ApiOperationError(error, 'file.download', {httpStatus: response.status}); } return response.blob(); } @@ -486,8 +551,8 @@ class TianShanAPI { body: content }); const json = await response.json(); - if (!response.ok) { - throw new Error(json.message || 'Upload failed'); + if (!response.ok || json.status !== 'uploaded' || (json.code !== undefined && json.code !== 0)) { + throw new ApiOperationError(json, 'file.upload', {httpStatus: response.status}); } return json; } @@ -512,7 +577,8 @@ class TianShanAPI { params.keyid = auth.keyid; } // 主机指纹验证参数 - params.trust_new = options.trust_new ?? true; // 新主机自动信任(默认 true) + params.trust_new = options.trust_new ?? false; // 新主机必须明确确认指纹 + params.confirmed_fingerprint = options.confirmed_fingerprint; params.accept_changed = options.accept_changed ?? false; // 指纹变化是否接受(默认 false) return this.call('ssh.test', params, 'POST'); } @@ -529,7 +595,8 @@ class TianShanAPI { params.keyid = auth.keyid; } // 主机指纹验证参数 - params.trust_new = options.trust_new ?? true; + params.trust_new = options.trust_new ?? false; + params.confirmed_fingerprint = options.confirmed_fingerprint; params.accept_changed = options.accept_changed ?? false; return this.call('ssh.exec', params, 'POST'); } @@ -538,7 +605,8 @@ class TianShanAPI { async sshCopyid(host, user, password, keyid, port = 22, verify = true, options = {}) { return this.call('ssh.copyid', { host, user, password, keyid, port, verify, - trust_new: options.trust_new ?? true, + trust_new: options.trust_new ?? false, + confirmed_fingerprint: options.confirmed_fingerprint, accept_changed: options.accept_changed ?? false }, 'POST'); } @@ -547,7 +615,8 @@ class TianShanAPI { async sshRevoke(host, user, password, keyid, port = 22, options = {}) { return this.call('ssh.revoke', { host, user, password, keyid, port, - trust_new: options.trust_new ?? true, + trust_new: options.trust_new ?? false, + confirmed_fingerprint: options.confirmed_fingerprint, accept_changed: options.accept_changed ?? false }, 'POST'); } diff --git a/components/ts_webui/web/js/app.js b/components/ts_webui/web/js/app.js index 77e01be..9def959 100644 --- a/components/ts_webui/web/js/app.js +++ b/components/ts_webui/web/js/app.js @@ -1,3 +1,18 @@ + +function runtimeText(key) { + const translated = typeof t === 'function' ? t('runtimeRepair.' + key) : ''; + return translated && translated !== 'runtimeRepair.' + key ? translated : key; +} +function runtimeSaveError(result) { + const code = result.data?.error_code || result.rawMessage || result.error || result.message; + const known = ['revision_conflict', 'source_read_only', 'recovery_required', 'commit_unknown', 'execution_busy', 'service_busy', 'busy_retired_config']; + return known.includes(code) ? runtimeText(code) : (typeof code === 'string' ? code : runtimeText('saveFailed')); +} +async function ruleWriteWithRevision(method, id) { + const current = await api.call('automation.rules.get', { id }); + if (current.code !== 0 || !Number.isInteger(current.data?.revision)) return current; + return api.call(method, { id, expected_revision: current.data.revision }); +} /** * TianshanOS Web App - Main Application */ @@ -7,6 +22,14 @@ if (typeof window.t === 'undefined') window.t = function(k) { return k; }; // 全局状态 // ========================================================================= +// Capture once at entry; do not ask which page is current after an await. +function capturePageValidity() { + const navigation = typeof router !== 'undefined' ? router.navigation : null; + const content = document.getElementById('page-content'); + return () => (typeof router === 'undefined' || router.navigation === navigation) && + (!navigation || navigation.isCurrent()) && document.getElementById('page-content') === content; +} + let ws = null; let refreshInterval = null; let subscriptionManager = null; // WebSocket 订阅管理器 @@ -169,15 +192,13 @@ document.addEventListener('DOMContentLoaded', () => { router.register('/automation', loadAutomationPage); // 语言切换时重新渲染当前页,使主内容使用新语言;下一帧恢复右上角登录态(避免 translateDOM 覆盖 #user-name) - window.addEventListener('languageChanged', () => { - if (typeof stopSystemPageTimers === 'function') { - stopSystemPageTimers(); - } - const loader = router.getCurrentLoader(); - if (loader) loader(); + window.addEventListener('languageChanged', (event) => { + if (event.detail?.initial) return; + router.navigate(); setTimeout(() => updateAuthUI(), 0); }); + window.dispatchEvent(new CustomEvent('appReady')); // 启动 WebSocket setupWebSocket(); @@ -303,12 +324,12 @@ document.getElementById('login-form')?.addEventListener('submit', async (e) => { async function logout() { try { - await api.logout(); - showToast(t('toast.loggedOut'), 'info'); + const result = await api.logout(); + if (api.token) return; // A newer sign-in owns the UI now. + showToast(t(result.serverConfirmed ? 'promptRepair.logoutConfirmed' : 'promptRepair.logoutLocal'), result.serverConfirmed ? 'info' : 'warning', 7000); } finally { updateAuthUI(); - window.location.hash = '/'; // 重定向到首页 - router.navigate(); + if (!api.token) router.navigate('/'); } } @@ -411,11 +432,29 @@ async function updateFooterVersion() { // WebSocket // ========================================================================= +let webSocketConnected = false; +function renderWsStatus(connected = webSocketConnected) { + webSocketConnected = connected; + const el = document.getElementById('ws-status'); + if (!el) return; + el.classList.toggle('connected', connected); + el.setAttribute('data-i18n-title', connected ? 'network.connected' : 'network.disconnected'); + el.title = t(connected ? 'network.connected' : 'network.disconnected'); + el.setAttribute('aria-label', el.title); +} +window.addEventListener('languageChanged', () => { + renderWsStatus(); + const toast = document.getElementById('toast'); + if (toast) { clearTimeout(toastTimer); toast.classList.remove('show'); toastDeadline = 0; } + if (lastPowerEvent) renderPowerNotice(lastPowerEvent); + updateModalWsStatus(webSocketConnected); +}); + function setupWebSocket() { ws = new TianShanWS( (msg) => handleEvent(msg), - () => document.getElementById('ws-status')?.classList.add('connected'), - () => document.getElementById('ws-status')?.classList.remove('connected') + () => renderWsStatus(true), + () => renderWsStatus(false) ); ws.connect(); @@ -511,18 +550,34 @@ function handleEvent(msg) { } // 处理电压保护事件 +let lastPowerEvent = null; +function renderPowerNotice(msg) { + let notice = document.getElementById('power-notice'); + if (!notice) { + notice = document.createElement('div'); notice.id = 'power-notice'; + notice.setAttribute('role', 'alert'); + notice.style.cssText = 'position:fixed;bottom:20px;left:20px;z-index:1100;background:#fff;padding:12px;border:2px solid #e11d48;white-space:pre-wrap'; + document.body.appendChild(notice); + } + const key = msg.state === 'PROTECTED' ? 'toast.voltageProtectionTriggered' : msg.state === 'RECOVERY' ? 'toast.voltageRecovering' : 'toast.lowVoltageWarning'; + notice.textContent = t(key, {voltage: msg.voltage?.toFixed(2) || '?', countdown: msg.countdown || 0}); + notice.hidden = !['LOW_VOLTAGE', 'SHUTDOWN', 'PROTECTED', 'RECOVERY'].includes(msg.state); +} + function handlePowerEvent(msg) { + lastPowerEvent = msg; + renderPowerNotice(msg); const state = msg.state; const voltage = msg.voltage?.toFixed(2) || '?'; const countdown = msg.countdown || 0; // 显示警告 if (state === 'LOW_VOLTAGE' || state === 'SHUTDOWN') { - showToast(typeof t === 'function' ? t('system.lowVoltageWarning', { voltage, countdown }) : `低电压警告: ${voltage}V (${countdown}s)`, 'warning', 5000); + showToast(typeof t === 'function' ? t('toast.lowVoltageWarning', { voltage, countdown }) : `低电压警告: ${voltage}V (${countdown}s)`, 'warning', 5000); } else if (state === 'PROTECTED') { - showToast(typeof t === 'function' ? t('system.voltageProtectionTriggered') : '电压保护已触发', 'error', 10000); + showToast(typeof t === 'function' ? t('toast.voltageProtectionTriggered') : '电压保护已触发', 'error', 10000); } else if (state === 'RECOVERY') { - showToast(typeof t === 'function' ? t('system.voltageRecovering', { voltage }) : `电压恢复中: ${voltage}V`, 'info', 3000); + showToast(typeof t === 'function' ? t('toast.voltageRecovering', { voltage }) : `电压恢复中: ${voltage}V`, 'info', 3000); } } @@ -531,6 +586,7 @@ function handlePowerEvent(msg) { // ========================================================================= async function loadSystemPage() { + const pageCurrent = capturePageValidity(); clearInterval(refreshInterval); // 取消之前设置的快捷操作刷新定时器(防止切换到其他页后仍触发) @@ -539,16 +595,6 @@ async function loadSystemPage() { quickActionsTimeoutId = null; } - // 取消之前的订阅 - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); // 取消聚合订阅 - subscriptionManager.unsubscribe('system.memory'); - subscriptionManager.unsubscribe('system.cpu'); - subscriptionManager.unsubscribe('network.status'); - subscriptionManager.unsubscribe('power.status'); - subscriptionManager.unsubscribe('fan.status'); - subscriptionManager.unsubscribe('service.list'); - } // 停止 uptime 计算 if (window.systemUptimeInterval) { @@ -760,19 +806,23 @@ async function loadSystemPage() { // 初始加载(不含快捷操作,避免 ssh.commands.list 慢响应阻塞) await refreshSystemPageOnce(); + if (!pageCurrent()) return; // 加载数据监控面板(优先执行,确保组件能实时获取变量数据) await initDataWidgets(); + if (!pageCurrent()) return; // 快捷操作延迟 2 秒后台加载,避免与 initDataWidgets 的首次变量刷新竞争 API quickActionsTimeoutId = setTimeout(() => { + if (!pageCurrent()) return; quickActionsTimeoutId = null; void refreshQuickActions(); }, 2000); // 订阅 WebSocket 实时更新 - 使用聚合订阅(system.dashboard) if (subscriptionManager) { - subscriptionManager.subscribe('system.dashboard', (msg) => { + const dashboardCallback = (msg) => { + if (!pageCurrent()) return; console.log('[System Page] Received dashboard:', msg); if (!msg.data) return; @@ -786,7 +836,10 @@ async function loadSystemPage() { if (data.power) updatePowerInfo(data.power); if (data.fan) updateFanInfo(data.fan); if (data.services) updateServiceList(data.services); - }, { interval: 1000 }); // 1秒更新所有数据 + }; + const manager = subscriptionManager; + manager.subscribe('system.dashboard', dashboardCallback, {interval: 1000}); + if (typeof router !== 'undefined') router.navigation?.onDispose(() => manager.unsubscribe('system.dashboard', dashboardCallback)); } // 启动浏览器本地时间更新定时器 @@ -831,37 +884,46 @@ async function loadSystemPage() { // 单次刷新(初始加载);refreshSystemPage 为别名,供时区/服务操作等调用 async function refreshSystemPageOnce() { + const pageCurrent = capturePageValidity(); // 系统信息 try { const info = await api.getSystemInfo(); + if (!pageCurrent()) return; if (info.data) { updateSystemInfo(info.data); } - } catch (e) { console.log('System info error:', e); } + } catch (e) { + if (!pageCurrent()) return; console.log('System info error:', e); } // 时间信息 try { const time = await api.timeInfo(); + if (!pageCurrent()) return; if (time.data) { updateTimeInfo(time.data); } - } catch (e) { console.log('Time info error:', e); } + } catch (e) { + if (!pageCurrent()) return; console.log('Time info error:', e); } // 内存 try { const mem = await api.getMemoryInfo(); + if (!pageCurrent()) return; if (mem.data) { updateMemoryInfo(mem.data); } - } catch (e) { console.log('Memory info error:', e); } + } catch (e) { + if (!pageCurrent()) return; console.log('Memory info error:', e); } // 网络 try { const netStatus = await api.networkStatus(); + if (!pageCurrent()) return; if (netStatus.data) { updateNetworkInfo(netStatus.data); } } catch (e) { + if (!pageCurrent()) return; document.getElementById('eth-status').textContent = '-'; document.getElementById('wifi-status').textContent = '-'; } @@ -869,15 +931,18 @@ async function refreshSystemPageOnce() { // 电源 try { const powerStatus = await api.powerStatus(); + if (!pageCurrent()) return; if (powerStatus.data) { updatePowerInfo(powerStatus.data); } const protStatus = await api.powerProtectionStatus(); + if (!pageCurrent()) return; if (protStatus.data) { const running = protStatus.data.running || protStatus.data.initialized; updateProtectionUI(running); } - } catch (e) { + } catch (e) { + if (!pageCurrent()) return; document.getElementById('voltage').textContent = '-'; document.getElementById('current').textContent = '-'; document.getElementById('power-watts').textContent = '-'; @@ -886,32 +951,40 @@ async function refreshSystemPageOnce() { // 风扇 try { const fans = await api.fanStatus(); + if (!pageCurrent()) return; updateFanInfo(fans.data); - } catch (e) { + } catch (e) { + if (!pageCurrent()) return; document.getElementById('fans-grid').innerHTML = '

' + t('fan.statusUnavailable') + '

'; } // 服务列表 try { const services = await api.serviceList(); + if (!pageCurrent()) return; updateServiceList(services.data); } catch (e) { + if (!pageCurrent()) return; console.log('Services error:', e); } // LED 设备 await refreshSystemLeds(); + if (!pageCurrent()) return; // 快捷操作已移至 loadSystemPage 末尾后台执行,避免阻塞 initDataWidgets // USB Mux 状态 await refreshUsbMuxStatus(); + if (!pageCurrent()) return; // AGX 电源状态 await refreshAgxPowerState(); + if (!pageCurrent()) return; // LPMU 状态检测 await refreshLpmuState(); + if (!pageCurrent()) return; } const refreshSystemPage = refreshSystemPageOnce; @@ -926,14 +999,17 @@ const USB_MUX_DISPLAY = { 'esp32': 'ESP', 'agx': 'AGX', 'lpmu': 'LPMU' }; const USB_MUX_COLORS = { 'esp32': '', 'agx': 'btn-service-style', 'lpmu': 'btn-success' }; async function refreshUsbMuxStatus() { + const pageCurrent = capturePageValidity(); try { const result = await api.call('device.usb.status'); + if (!pageCurrent()) return; if (result.code === 0 && result.data) { usbMuxConfigured = result.data.configured !== false; usbMuxTarget = result.data.target || 'esp32'; updateUsbMuxButton(); } } catch (e) { + if (!pageCurrent()) return; console.warn('USB Mux status unavailable:', e.message); usbMuxConfigured = false; updateUsbMuxButton(); @@ -1054,13 +1130,16 @@ async function toggleUsbMux() { let agxPowerState = false; // false=断电(HIGH), true=上电(LOW) async function refreshAgxPowerState() { + const pageCurrent = capturePageValidity(); try { const result = await api.call('device.status', { device: 'agx' }); + if (!pageCurrent()) return; if (result.code === 0 && result.data) { agxPowerState = result.data.state === 'on' || result.data.state === 'booting'; updateAgxPowerButton(); } } catch (e) { + if (!pageCurrent()) return; console.warn('AGX status unavailable:', e.message); } } @@ -1110,7 +1189,7 @@ let lpmuPollingStartTime = 0; let lpmuPollingMode = 'startup'; // 'startup' | 'shutdown' async function toggleLpmuPower() { - if (!confirm(t('system.lpmuTriggerConfirm'))) { + if (!confirmAction(t('system.lpmuTriggerConfirm'))) { return; } @@ -1135,71 +1214,43 @@ async function toggleLpmuPower() { } // 启动 LPMU 状态轮询(触发电源后调用) +let lpmuPollGeneration = 0; function startLpmuStatePolling(wasOnline = false) { stopLpmuStatePolling(); - + const generation = lpmuPollGeneration; lpmuState = 'detecting'; lpmuPollingMode = wasOnline ? 'shutdown' : 'startup'; updateLpmuPowerButton(); - lpmuPollingStartTime = Date.now(); - const minWaitSec = wasOnline ? 40 : 0; const maxWaitSec = wasOnline ? 60 : 80; - + let pending = false; lpmuPollingInterval = setInterval(async () => { - const elapsed = (Date.now() - lpmuPollingStartTime) / 1000; - const remaining = Math.round(maxWaitSec - elapsed); - - let isReachable = false; + if (pending) return; + pending = true; + let reachable = null; try { - const result = await api.call('device.ping', { host: '10.10.99.99', timeout: 1000 }); - isReachable = result.code === 0 && result.data && result.data.reachable; - } catch (e) {} - - if (lpmuPollingMode === 'startup') { - if (isReachable) { - lpmuState = 'online'; - updateLpmuPowerButton(); - stopLpmuStatePolling(); - showToast(t('system.lpmuOnlineSuccess') + ' (' + Math.round(elapsed) + (getLanguage() === 'zh-CN' ? '秒' : 's') + ')', 'success'); - return; - } - updateLpmuPowerButton(remaining); - if (elapsed >= maxWaitSec) { - lpmuState = 'offline'; - updateLpmuPowerButton(); - stopLpmuStatePolling(); - showToast(t('system.lpmuStartupTimeout'), 'warning'); - } - } else { - if (elapsed < minWaitSec) { - updateLpmuPowerButton(remaining); - return; - } - if (!isReachable) { - lpmuState = 'offline'; - updateLpmuPowerButton(); - stopLpmuStatePolling(); - showToast(t('system.lpmuOfflineSuccess') + ' (' + Math.round(elapsed) + (getLanguage() === 'zh-CN' ? '秒' : 's') + ')', 'success'); - return; - } - updateLpmuPowerButton(remaining); - if (elapsed >= maxWaitSec) { - lpmuState = 'online'; - updateLpmuPowerButton(); - stopLpmuStatePolling(); - showToast(t('system.lpmuShutdownTimeout'), 'warning'); - } - } + const result = requireApiSuccess(await api.call('device.ping', {host: '10.10.99.99', timeout: 1000}), 'device.ping'); + if (typeof result.data?.reachable === 'boolean') reachable = result.data.reachable; + } catch (error) { console.warn('LPMU reachability check failed', error); } + finally { pending = false; } + if (generation !== lpmuPollGeneration) return; + const elapsed = (Date.now() - lpmuPollingStartTime) / 1000; + const reachedTarget = elapsed >= minWaitSec && reachable === !wasOnline; + if (reachedTarget || elapsed >= maxWaitSec) { + lpmuState = reachable === null ? 'unknown' : reachable ? 'online' : 'offline'; + stopLpmuStatePolling(); + updateLpmuPowerButton(); + const key = reachable === null ? 'lpmuProbeFailed' : reachable ? 'lpmuReachable' : 'lpmuUnreachable'; + showToast(t('promptRepair.' + key), 'info', 7000); + } else updateLpmuPowerButton(Math.max(0, Math.ceil(maxWaitSec - elapsed))); }, 5000); } function stopLpmuStatePolling() { - if (lpmuPollingInterval) { - clearInterval(lpmuPollingInterval); - lpmuPollingInterval = null; - } + lpmuPollGeneration++; + if (lpmuPollingInterval) clearInterval(lpmuPollingInterval); + lpmuPollingInterval = null; } function startDeviceStateMonitor() { @@ -1227,16 +1278,19 @@ function stopDeviceStateMonitor() { } async function refreshLpmuState() { + const pageCurrent = capturePageValidity(); if (lpmuPollingInterval) return; try { const result = await api.call('device.ping', { host: '10.10.99.99', timeout: 1000 }); - if (result.code === 0 && result.data) { + if (!pageCurrent()) return; + if (result.code === 0 && typeof result.data?.reachable === 'boolean') { lpmuState = result.data.reachable ? 'online' : 'offline'; } else { lpmuState = 'unknown'; } } catch (e) { + if (!pageCurrent()) return; lpmuState = 'unknown'; } updateLpmuPowerButton(); @@ -1370,7 +1424,7 @@ function updateMemoryInfo(data) { document.getElementById('psram-text').textContent = `${formatBytes(psramUsed)} / ${formatBytes(psramTotal)} (${psramPercent}%)`; } else { - document.getElementById('psram-text').textContent = typeof t === 'function' ? t('otaPage.psramUnavailable') : '不可用'; + document.getElementById('psram-text').textContent = typeof t === 'function' ? t('ui.psramUnavailable') : '不可用'; } } @@ -1654,8 +1708,8 @@ function updateServiceList(data) { svc.state === 'ERROR' ? 'status-error' : 'status-warn'; tr.innerHTML = ` ${svc.name} - ${svc.state} - ${svc.phase} + ${userStateLabel(svc.state)} + ${servicePhaseLabel(svc.phase)} ${svc.healthy ? '' : ''} @@ -1729,15 +1783,15 @@ function hideServicesModal() { async function setFanSpeed(id, speed) { try { - await api.fanSet(id, parseInt(speed)); + requireApiSuccess(await api.fanSet(id, parseInt(speed)), 'fanSet'); showToast(typeof t === 'function' ? t('fan.speedSet', { id, speed }) : `风扇 ${id} 速度已设置为 ${speed}%`, 'success'); } catch (e) { showToast((typeof t === 'function' ? t('fan.setFanFailed', { msg: e.message }) : '设置风扇失败: ' + e.message), 'error'); } } async function setFanMode(id, mode) { try { - await api.call('fan.mode', { id: id, mode: mode }); - showToast(typeof t === 'function' ? t('fan.modeSwitch', { id, mode }) : `风扇 ${id} 模式已切换为 ${mode}`, 'success'); + requireApiSuccess(await api.call('fan.mode', { id: id, mode: mode }), 'call'); + showToast(typeof t === 'function' ? t('fan.modeSwitch', { id, mode: t({off:'common.disabled', manual:'common.manual', auto:'common.auto', curve:'fan.curve'}[mode] || 'common.unknown') }) : `风扇 ${id} 模式已切换为 ${mode}`, 'success'); await refreshFans(); } catch (e) { showToast((typeof t === 'function' ? t('fan.setFanModeFailed', { msg: e.message }) : '设置风扇模式失败: ' + e.message), 'error'); } } @@ -1962,14 +2016,14 @@ function buildVarSelectOptions(selectedName) { let html = ''; if (priorityVars.length > 0) { - html += ``; + html += ``; priorityVars.forEach(v => { html += renderOption(v); }); html += ``; } if (otherVars.length > 0) { - html += ``; + html += ``; otherVars.forEach(v => { html += renderOption(v); }); @@ -1979,7 +2033,7 @@ function buildVarSelectOptions(selectedName) { /* 如果已选变量不在列表中,追加显示 */ if (selectedName && !availableTempVars.find(v => v.name === selectedName)) { const safeName = typeof escapeHtml === 'function' ? escapeHtml(selectedName) : selectedName; - html += ``; + html += ``; } return html; @@ -2474,7 +2528,7 @@ async function bindTempVariable() { const result = await api.call('temp.bind', { variables }); if (result.code === 0) { - await api.call('temp.select', { source: 'variable' }); + requireApiSuccess(await api.call('temp.select', { source: 'variable' }), 'call'); showToast(t('fanPage.tempBoundWeighted', { count: variables.length }), 'success'); @@ -2561,7 +2615,7 @@ async function applyFanCurve() { }); if (limitsResult.code !== 0) { - throw new Error(limitsResult.message || '设置占空比限制失败'); + throw new Error(limitsResult.message || t('dataWidget.setDutyLimitFailed')); } // 2. 设置曲线(同时传递 hysteresis 和 min_interval,会自动保存到 NVS) @@ -2573,7 +2627,7 @@ async function applyFanCurve() { }); if (curveResult.code !== 0) { - throw new Error(curveResult.message || '设置曲线失败'); + throw new Error(curveResult.message || t('dataWidget.setCurveFailed')); } // 3. 切换到曲线模式 @@ -2583,7 +2637,7 @@ async function applyFanCurve() { }); if (modeResult.code !== 0) { - throw new Error(modeResult.message || '切换模式失败'); + throw new Error(modeResult.message || t('promptRepair.modeFailed')); } showToast(typeof t === 'function' ? t('fanPage.curveApplied', { id: fanId }) : `风扇 ${fanId} 曲线已应用并保存`, 'success'); @@ -2758,10 +2812,10 @@ async function updateFanCurvePreview() { async function serviceAction(name, action) { try { - if (action === 'restart') await api.serviceRestart(name); - else if (action === 'start') await api.serviceStart(name); - else if (action === 'stop') await api.serviceStop(name); - showToast(typeof t === 'function' ? t('toast.serviceSuccess', { name, action }) : `服务 ${name} ${action} 成功`, 'success'); + if (action === 'restart') requireApiSuccess(await api.serviceRestart(name), 'service.restart'); + else if (action === 'start') requireApiSuccess(await api.serviceStart(name), 'service.start'); + else if (action === 'stop') requireApiSuccess(await api.serviceStop(name), 'service.stop'); + showToast(typeof t === 'function' ? t({start:'promptRepair.serviceStarted', stop:'promptRepair.serviceStopped', restart:'promptRepair.serviceRestarted'}[action], {name}) : `服务 ${name} ${action} 成功`, 'success'); await refreshSystemPage(); } catch (e) { showToast(typeof t === 'function' ? t('toast.operationFailedMsg', { msg: e.message }) : `操作失败: ${e.message}`, 'error'); @@ -2769,11 +2823,11 @@ async function serviceAction(name, action) { } function confirmReboot() { - if (confirm(t('system.rebootConfirm'))) { + if (confirmAction(t('system.rebootConfirm'))) { showToast(t('system.rebootSending'), 'info'); api.reboot(500) .then((result) => { - console.log('Reboot response:', result); + requireApiSuccess(result, 'system.reboot'); showToast(t('system.rebootingPleaseWait'), 'success'); }) .catch((err) => { @@ -2786,11 +2840,13 @@ function confirmReboot() { // LED 控制(系统页面内嵌版) async function refreshSystemLeds() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('system-led-devices-grid'); if (!container) return; try { const result = await api.ledList(); + if (!pageCurrent()) return; if (result.data && result.data.devices && result.data.devices.length > 0) { // 存储设备信息 @@ -2820,14 +2876,15 @@ async function refreshSystemLeds() { container.innerHTML = `
-

未找到 LED 设备

-

LED 设备可能尚未启动

+

${t('ledPage.ledNotFound')}

+

${t('ledPage.ledNotStarted')}

`; } } catch (e) { + if (!pageCurrent()) return; console.error('LED list error:', e); - container.innerHTML = `
${typeof t === 'function' ? t('common.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message}
`; + container.innerHTML = `
${escapeHtml(typeof t === 'function' ? t('common.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message)}
`; } } @@ -2838,69 +2895,69 @@ async function refreshSystemLeds() { */ const WIDGET_TYPES = { ring: { - name: '环形进度', + get name() { return t('dataWidget.typeRing'); }, icon: '', - description: '圆环百分比,适合 CPU/内存/磁盘使用率', + get description() { return t('dataWidget.typeRingDesc'); }, defaultConfig: { min: 0, max: 100, unit: '%', color: '#4dabf7', decimals: 0 } }, gauge: { - name: '仪表盘', + get name() { return t('dataWidget.typeGauge'); }, icon: '', - description: '半圆仪表,适合带刻度的数值', + get description() { return t('dataWidget.typeGaugeDesc'); }, defaultConfig: { min: 0, max: 100, unit: '', color: '#69db7c', decimals: 1 } }, temp: { - name: '温度计', + get name() { return t('dataWidget.typeTemp'); }, icon: '', - description: '垂直温度条,颜色随温度变化', + get description() { return t('dataWidget.typeTempDesc'); }, defaultConfig: { min: 0, max: 100, unit: '°C', color: '#ff8787', decimals: 0 } }, number: { - name: '数字', + get name() { return t('dataWidget.typeNumber'); }, icon: '', - description: '大号数字显示,适合功率/电压/电流', + get description() { return t('dataWidget.typeNumberDesc'); }, defaultConfig: { unit: 'W', color: '#74c0fc', icon: '', decimals: 1 } }, bar: { - name: '进度条', + get name() { return t('dataWidget.typeBar'); }, icon: '', - description: '水平进度条', + get description() { return t('dataWidget.typeBarDesc'); }, defaultConfig: { min: 0, max: 100, unit: '%', color: '#ffd43b', decimals: 1 } }, text: { - name: '文本', + get name() { return t('led.text'); }, icon: '', - description: '显示文本或格式化字符串', + get description() { return t('dataWidget.typeTextDesc'); }, defaultConfig: { unit: '', color: '#9ca3af' } }, status: { - name: '状态灯', + get name() { return t('dataWidget.typeStatus'); }, icon: '', - description: '根据值显示不同颜色状态', + get description() { return t('dataWidget.typeStatusDesc'); }, defaultConfig: { thresholds: [0, 50, 80], colors: ['#40c057', '#fab005', '#fa5252'] } }, icon: { - name: '图标状态', + get name() { return t('dataWidget.typeIcon'); }, icon: '', - description: '根据值显示不同图标', + get description() { return t('dataWidget.typeIconDesc'); }, defaultConfig: { icons: { '0': '', '1': '', 'default': '' } } }, dual: { - name: '双数值', + get name() { return t('dataWidget.typeDual'); }, icon: '', - description: '主值+副值,适合显示当前/最大等', + get description() { return t('dataWidget.typeDualDesc'); }, defaultConfig: { unit: '', color: '#74c0fc', decimals: 1 } }, percent: { - name: '百分比', + get name() { return t('dataWidget.typePercent'); }, icon: '', - description: '大号百分比数字', + get description() { return t('dataWidget.typePercentDesc'); }, defaultConfig: { min: 0, max: 100, color: '#4dabf7', decimals: 0 } }, log: { - name: '日志流', + get name() { return t('dataWidget.typeLog'); }, icon: '', - description: '从变量读取日志文本流,支持手动刷新', + get description() { return t('dataWidget.typeLogDesc'); }, defaultConfig: { maxLines: 15, color: '#495057', fullWidth: true } } }; @@ -2910,11 +2967,11 @@ const WIDGET_TYPES = { */ const LAYOUT_OPTIONS = { width: [ - { value: 'auto', label: '自动', desc: '根据内容自适应' }, - { value: 'small', label: '小', desc: '1/4 宽度' }, - { value: 'medium', label: '中', desc: '1/2 宽度' }, - { value: 'large', label: '大', desc: '3/4 宽度' }, - { value: 'full', label: '整行', desc: '独占一整行' } + { value: 'auto', get label() { return t('runtimeRepair.automatic'); }, get desc() { return t('dataWidget.layoutAutoDesc'); } }, + { value: 'small', get label() { return t('dataWidget.layoutSmall'); }, get desc() { return t('dataWidget.layoutSmallDesc'); } }, + { value: 'medium', get label() { return t('dataWidget.layoutMedium'); }, get desc() { return t('dataWidget.layoutMediumDesc'); } }, + { value: 'large', get label() { return t('dataWidget.layoutLarge'); }, get desc() { return t('dataWidget.layoutLargeDesc'); } }, + { value: 'full', get label() { return t('dataWidget.layoutFull'); }, get desc() { return t('dataWidget.layoutFullDesc'); } } ] }; @@ -2923,17 +2980,17 @@ const LAYOUT_OPTIONS = { */ const WIDGET_PRESETS = [ { id: 'cpu', label: 'CPU', type: 'ring', icon: '', color: '#4dabf7', unit: '%' }, - { id: 'mem', label: '内存', type: 'ring', icon: '', color: '#69db7c', unit: '%' }, - { id: 'disk', label: '硬盘', type: 'ring', icon: '', color: '#ffd43b', unit: '%' }, - { id: 'temp', label: '温度', type: 'temp', icon: '', color: '#ff8787', unit: '°C' }, + { id: 'mem', get label() { return t('system.memory'); }, type: 'ring', icon: '', color: '#69db7c', unit: '%' }, + { id: 'disk', get label() { return t('dataWidget.presetDisk'); }, type: 'ring', icon: '', color: '#ffd43b', unit: '%' }, + { id: 'temp', get label() { return t('fan.temperature'); }, type: 'temp', icon: '', color: '#ff8787', unit: '°C' }, { id: 'gpu', label: 'GPU', type: 'ring', icon: '', color: '#da77f2', unit: '%' }, - { id: 'power', label: '功耗', type: 'number', icon: '', color: '#74c0fc', unit: 'W' }, - { id: 'voltage', label: '电压', type: 'number', icon: '', color: '#ffa94d', unit: 'V' }, - { id: 'current', label: '电流', type: 'number', icon: '', color: '#ff6b6b', unit: 'A' }, - { id: 'network', label: '网速', type: 'bar', icon: '', color: '#38d9a9', unit: 'Mbps' }, - { id: 'status', label: '状态', type: 'status', icon: '', color: '#40c057', unit: '' }, - { id: 'uptime', label: '运行时间', type: 'text', icon: '', color: '#9ca3af', unit: '' }, - { id: 'log', label: '日志流', type: 'log', icon: '', color: '#495057', maxLines: 15, layout: 'full' }, + { id: 'power', get label() { return t('dataWidget.presetPower'); }, type: 'number', icon: '', color: '#74c0fc', unit: 'W' }, + { id: 'voltage', get label() { return t('system.voltage'); }, type: 'number', icon: '', color: '#ffa94d', unit: 'V' }, + { id: 'current', get label() { return t('system.current'); }, type: 'number', icon: '', color: '#ff6b6b', unit: 'A' }, + { id: 'network', get label() { return t('dataWidget.presetNetwork'); }, type: 'bar', icon: '', color: '#38d9a9', unit: 'Mbps' }, + { id: 'status', get label() { return t('common.status'); }, type: 'status', icon: '', color: '#40c057', unit: '' }, + { id: 'uptime', get label() { return t('system.uptime'); }, type: 'text', icon: '', color: '#9ca3af', unit: '' }, + { id: 'log', get label() { return t('dataWidget.typeLog'); }, type: 'log', icon: '', color: '#495057', maxLines: 15, layout: 'full' }, ]; // 当前配置的组件列表 @@ -2954,9 +3011,11 @@ let dataWidgetsRefreshing = false; * 优先级:后端 API (SD卡/NVS) > localStorage (兼容旧版) */ async function loadDataWidgets() { + const pageCurrent = capturePageValidity(); try { // 1. 尝试从后端加载 const response = await api.call('ui.widgets.get'); + if (!pageCurrent()) return; // API 响应格式: {code: 0, data: {widgets: [...], refresh_interval: 5000, source: "sdcard"}} if (response && response.code === 0 && response.data && response.data.widgets) { const result = response.data; @@ -2972,6 +3031,7 @@ async function loadDataWidgets() { console.log(`从 localStorage 迁移 ${localData.length} 个组件到后端`); // 保存到后端 await saveDataWidgets(); + if (!pageCurrent()) return; } } // 修复已损坏的图标数据 @@ -2979,6 +3039,7 @@ async function loadDataWidgets() { return; } } catch (e) { + if (!pageCurrent()) return; console.warn('从后端加载数据组件配置失败:', e); } @@ -3121,6 +3182,7 @@ function startDataWidgetsAutoRefresh() { * 停止自动刷新 */ function stopDataWidgetsAutoRefresh() { + dataWidgetsRefreshing = false; if (dataWidgetsIntervalId) { clearInterval(dataWidgetsIntervalId); dataWidgetsIntervalId = null; @@ -3513,10 +3575,13 @@ function updateWidgetValue(widget, value) { * 初始化数据组件面板 */ async function initDataWidgets() { - await loadDataWidgets(); // 异步加载(优先后端 API) + const pageCurrent = capturePageValidity(); + await loadDataWidgets(); + if (!pageCurrent()) return; // 异步加载(优先后端 API) loadDataWidgetsRefreshInterval(); // 兼容性保留 renderDataWidgets(); await refreshDataWidgets(); + if (!pageCurrent()) return; startDataWidgetsAutoRefresh(); } @@ -3525,6 +3590,7 @@ async function initDataWidgets() { * 使用 automation.variables.list 一次获取全部变量,避免 N 次 get 串行调用 */ async function refreshDataWidgets() { + const pageCurrent = capturePageValidity(); if (dataWidgetsRefreshing) return; dataWidgetsRefreshing = true; @@ -3551,6 +3617,7 @@ async function refreshDataWidgets() { if (varNames.size > 0) { try { const resp = await api.call('automation.variables.list', { include_meta: false }); + if (!pageCurrent()) return; if (resp.code === 0 && resp.data?.variables) { for (const v of resp.data.variables) { if (varNames.has(v.name) && v.value !== undefined) { @@ -3559,6 +3626,7 @@ async function refreshDataWidgets() { } } } catch (e) { + if (!pageCurrent()) return; console.warn('获取变量列表失败:', e); } } @@ -3578,7 +3646,7 @@ async function refreshDataWidgets() { } } } finally { - dataWidgetsRefreshing = false; + if (pageCurrent()) dataWidgetsRefreshing = false; } } @@ -3717,6 +3785,7 @@ function updateLogToggleButton(widgetId, isReading) { * 刷新日志组件一次(从变量读取) */ async function refreshLogOnce(widgetId) { + const pageCurrent = capturePageValidity(); const widget = dataWidgets.find(w => w.id === widgetId); if (!widget) return; @@ -3738,6 +3807,7 @@ async function refreshLogOnce(widgetId) { const varName = varMatch[1].trim(); const result = await api.call('automation.variables.get', { name: varName }); + if (!pageCurrent()) return; if (result.code !== 0 || result.data?.value === undefined) { container.innerHTML = '
' + (typeof t === 'function' ? t('fanPage.variableNoData') : '变量不存在或无数据') + '
'; @@ -3748,6 +3818,7 @@ async function refreshLogOnce(widgetId) { appendLogToWidget(widget.id, logText, widget.maxLines || 15); } catch (e) { + if (!pageCurrent()) return; console.warn('获取日志变量失败:', e); container.innerHTML = '
' + (typeof t === 'function' ? t('fanPage.readFailed') : '读取失败') + '
'; } @@ -4116,7 +4187,7 @@ function showWidgetEditPanel(widgetId) { main.innerHTML = `
- ${typeConfig.icon || ''} ${typeof t === 'function' ? (t('dataWidget.widgetType' + (widget.type ? widget.type.charAt(0).toUpperCase() + widget.type.slice(1) : '')) || typeConfig.name) : (typeConfig.name || widget.type)} + ${typeConfig.icon || ''} ${typeof t === 'function' ? (typeConfig.name || t('common.unknown')) : (typeConfig.name || widget.type)}
@@ -4290,7 +4361,7 @@ function deleteDataWidget(widgetId) { const widget = dataWidgets[idx]; - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteWidget', { label: widget.label }) : `确定要删除"${widget.label}"组件吗?`)) return; + if (!confirmAction(typeof t === 'function' ? t('ui.confirmDeleteWidget', { label: widget.label }) : `确定要删除"${widget.label}"组件吗?`)) return; dataWidgets.splice(idx, 1); saveDataWidgets(); @@ -4319,6 +4390,7 @@ let _sshExecCircuitBreaker = { failUntil: 0, failCount: 0 }; * 刷新快捷操作面板 */ async function refreshQuickActions() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('quick-actions-grid'); if (!container) { return; @@ -4328,17 +4400,23 @@ async function refreshQuickActions() { // 确保 SSH 主机数据已加载(用于 nohup 按钮) if (!window._sshHostsData || Object.keys(window._sshHostsData).length === 0) { await loadSshHostsData(); + if (!pageCurrent()) return; } // 强制刷新 SSH 命令缓存,确保 nohup/serviceMode 等字段为最新 await loadSshCommands(); + if (!pageCurrent()) return; const result = await api.call('automation.rules.list'); + if (!pageCurrent()) return; if (result.code === 0 && result.data && result.data.rules) { // 过滤出启用且标记为可手动触发的规则 + if (!result.data.loaded || result.data.recovery_required) { + container.textContent = runtimeText(result.data.recovery_required ? 'recovery_required' : 'configLoading'); return; + } const allRules = result.data.rules; - const manualRules = allRules.filter(r => r.enabled && r.manual_trigger); + const manualRules = allRules.filter(r => r.show_on_dashboard === true); // 按 localStorage 保存的顺序排列快捷操作 let savedOrder = []; @@ -4348,7 +4426,8 @@ async function refreshQuickActions() { savedOrder = JSON.parse(raw); if (!Array.isArray(savedOrder)) savedOrder = []; } - } catch (e) { savedOrder = []; } + } catch (e) { + if (!pageCurrent()) return; savedOrder = []; } if (savedOrder.length > 0) { manualRules.sort((a, b) => { const ia = savedOrder.indexOf(a.id); @@ -4375,80 +4454,33 @@ async function refreshQuickActions() { } const nohupInfo = await checkRuleHasNohupSsh(rule); + if (!pageCurrent()) return; let nohupBtns = ''; let isRunning = false; - if (nohupInfo) { - const cbOpen = Date.now() < _sshExecCircuitBreaker.failUntil; - if (cbOpen) { - console.info('[SSH CircuitBreaker] Skipping ssh.exec check for', rule.id, - '(cooldown', Math.round((_sshExecCircuitBreaker.failUntil - Date.now()) / 1000), 's)'); - isRunning = false; - } else try { - const host = window._sshHostsData?.[nohupInfo.hostId]; - if (host) { - const checkResult = await api.call('ssh.exec', { - host: host.host, - port: host.port, - user: host.username, - keyid: host.keyid, - command: nohupInfo.checkCmd, - timeout_ms: 5000 - }); - const stdout = (checkResult.data?.stdout || '').trim(); - isRunning = stdout.includes('running'); - _sshExecCircuitBreaker.failCount = 0; - _sshExecCircuitBreaker.failUntil = 0; - } - } catch (e) { - console.warn('Check process status failed for rule', rule.id, e); - isRunning = false; - _sshExecCircuitBreaker.failCount++; - const backoff = Math.min(60, 15 * _sshExecCircuitBreaker.failCount); - _sshExecCircuitBreaker.failUntil = Date.now() + backoff * 1000; - console.warn(`[SSH CircuitBreaker] SSH exec failed ${_sshExecCircuitBreaker.failCount}x, cooling down ${backoff}s`); - } - - const statusIcon = isRunning ? '' : ''; - const statusTitle = isRunning ? (typeof t === 'function' ? t('automationPage.processRunning') : '进程运行中') : (typeof t === 'function' ? t('automationPage.processNotRunning') : '进程未运行'); - let serviceStatusHtml = ''; - if (nohupInfo.serviceMode && nohupInfo.varName && isRunning) { - serviceStatusHtml = ` -
- ... -
- `; - } - const viewLogText = typeof t === 'function' ? t('automationPage.logTitle') : '日志'; - const stopText = typeof t === 'function' ? t('automationPage.stopProcess') : '停止'; - const viewLogTitle = typeof t === 'function' ? t('automationPage.viewLog') : '查看日志'; - const stopTitle = typeof t === 'function' ? t('ssh.stopProcess') : '终止进程'; + if (nohupInfo?.serviceMode) { nohupBtns = ` - ${statusIcon} - ${serviceStatusHtml} -
- - +
+ ${runtimeText('unknown')}
- `; +
+ + +
`; } - - const processRunningMsg = typeof t === 'function' ? t('toast.processRunning') : '进程正在运行中,请先停止'; - const cardOnClick = (nohupInfo && isRunning) - ? `showToast(${JSON.stringify(processRunningMsg)}, 'warning')` - : `triggerQuickAction('${escapeHtml(rule.id)}')`; + const cardOnClick = `triggerQuickAction('${escapeHtml(rule.id)}')`; const cleanName = rule.name.replace(/^[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1F1E0}-\u{1F1FF}\u200D]+\s*/gu, '').trim(); cardsHtml.push(`
${iconHtml}
${escapeHtml(cleanName)}
+ ${runtimeText(!rule.enabled ? 'disabled' : rule.manual_trigger ? 'manual' : 'automatic')}${(rule.reference_unresolved || nohupInfo?.unresolved) ? ' · ' + runtimeText('referenceUnresolved') : ''} ${nohupBtns}
`); @@ -4473,6 +4505,7 @@ async function refreshQuickActions() { container.innerHTML = '

' + (typeof t === 'function' ? (t('automationPage.loadQuickActionsFailed') || '无法加载快捷操作') : '无法加载快捷操作') + '

'; } } catch (e) { + if (!pageCurrent()) return; console.error('Quick actions error:', e); container.innerHTML = '

' + (typeof t === 'function' ? t('filePage.loadFailed') : '加载失败') + '

'; } @@ -4505,42 +4538,33 @@ function stopServiceStatusRefresh() { } } +let serviceStatusInFlight = false; async function updateQuickActionServiceStatus() { - const statusContainers = document.querySelectorAll('.quick-action-service-status'); - if (statusContainers.length === 0) return; - - for (const container of statusContainers) { - const varName = container.dataset.var; - if (!varName) continue; - - const valueEl = container.querySelector('.service-value'); - if (!valueEl) continue; - - // 检查进程是否运行(通过 data-running 属性) - const isRunning = container.dataset.running === 'true'; - - // 如果进程未运行,始终显示"未启动" - if (!isRunning) { - valueEl.textContent = (typeof t === 'function' ? t('sshPage.statusIdle') : '未启动'); - container.className = 'quick-action-service-status status-idle'; - continue; - } - - try { - const result = await api.call('automation.variables.get', { name: `${varName}.status` }); - if (result && result.data && result.data.value !== undefined) { - const status = result.data.value; - valueEl.textContent = getServiceStatusLabel(status); - container.className = `quick-action-service-status status-${status}`; - } else { - valueEl.textContent = (typeof t === 'function' ? t('sshPage.statusChecking') : '检测中'); - container.className = 'quick-action-service-status status-checking'; + if (document.hidden || serviceStatusInFlight) return; + serviceStatusInFlight = true; + try { + for (const container of document.querySelectorAll('.quick-action-service-status')) { + if (!container.isConnected || document.hidden) break; + const card = container.closest('.quick-action-card'); + const commandId = container.dataset.command; + try { + const response = await api.call('automation.services.status', { command_id: commandId }); + if (!container.isConnected || container.dataset.command !== commandId) continue; + const data = response.data || {}; + const state = response.code === 0 ? data.state : 'unknown'; + card.dataset.state = state; + container.querySelector('.service-value').textContent = runtimeText(state) + + (data.last_known && state === 'unknown' ? ' · ' + runtimeText('lastKnown') + ': ' + runtimeText(data.last_known) : '') + + (data.confirmed_ms ? ' · ' + runtimeText('confirmedAt') + ' ' + Math.floor(data.confirmed_ms / 1000) + 's' : ''); + container.title = runtimeText('stateEvidence') + ': ' + (data.source || 'none'); + } catch (_) { + if (container.isConnected) { + card.dataset.state = 'unknown'; + container.querySelector('.service-value').textContent = runtimeText('unknown'); + } } - } catch (e) { - valueEl.textContent = (typeof t === 'function' ? t('sshPage.statusUnknown') : '未知'); - container.className = 'quick-action-service-status status-unknown'; } - } + } finally { serviceStatusInFlight = false; } } // 触发快捷操作后的冷却时间(毫秒),避免连续触发导致后端只执行最后一个 @@ -4550,6 +4574,15 @@ let quickActionsTimeoutId = null; // 用于导航时取消,避免 quick-actio /** 供 router 在页面切换时取消快捷操作定时器,并销毁拖拽排序(防止 ghost 残留) */ window.stopSystemPageTimers = function() { + clearInterval(refreshInterval); + refreshInterval = null; + clearInterval(localTimeInterval); + localTimeInterval = null; + clearInterval(window.systemUptimeInterval); + window.systemUptimeInterval = null; + stopLpmuStatePolling(); + for (const id of Object.keys(logWidgetTimers)) stopLogReading(id); + stopServiceStatusRefresh(); if (quickActionsTimeoutId) { clearTimeout(quickActionsTimeoutId); quickActionsTimeoutId = null; @@ -4569,13 +4602,23 @@ window.stopSystemPageTimers = function() { * @param {string} ruleId - 规则 ID */ async function triggerQuickAction(ruleId) { - const card = event?.currentTarget || document.getElementById(`quick-action-${ruleId}`); + const card = document.getElementById(`quick-action-${ruleId}`); if (!card) { console.error('triggerQuickAction: card not found for ruleId=', ruleId); showToast((typeof t === 'function' ? t('toast.cardNotFound') : '无法找到操作卡片'), 'error'); return; } + // A user start request may verify unknown state. Periodic refresh remains local. + if (card.dataset.allowed === 'true' && card.dataset.service && card.dataset.state === 'unknown') { + try { + const checked = await api.call('automation.services.status', { command_id: card.dataset.service, verify: true }); + card.dataset.state = checked.code === 0 ? checked.data?.state || 'unknown' : 'unknown'; + } catch (_) { card.dataset.state = 'unknown'; } + } + if (card.dataset.allowed !== 'true' || (card.dataset.service && card.dataset.state !== 'stopped')) { + showToast(runtimeText('startBlocked'), 'warning'); return; + } if (card.classList.contains('triggering')) { showToast(typeof t === 'function' ? t('toast.processing') : 'Operation in progress...', 'warning'); return; @@ -4590,6 +4633,7 @@ async function triggerQuickAction(ruleId) { try { // 添加按下效果并禁用点击 card.classList.add('triggering'); + if (card.dataset.service) card.dataset.state = 'starting'; card.style.pointerEvents = 'none'; // 禁用点击防止重复 // 更新图标显示加载状态 @@ -4620,7 +4664,8 @@ async function triggerQuickAction(ruleId) { card.classList.remove('triggering'); } catch (e) { console.error('triggerQuickAction error:', e); - showToast((typeof t === 'function' ? t('toast.execFailedMsg', { msg: e.message }) : '执行失败: ' + e.message), 'error'); + showToast(runtimeText('outcomeUnknown'), 'error'); + if (card?.dataset.service) card.dataset.state = 'unknown'; if (card) { card.classList.remove('triggering'); card.style.pointerEvents = ''; @@ -4643,7 +4688,7 @@ async function checkRuleHasNohupSsh(rule) { try { const detailResult = await api.call('automation.rules.get', { id: rule.id }); if (detailResult.code !== 0 || !detailResult.data || !detailResult.data.actions) { - return null; + return { unresolved: true }; } const actions = detailResult.data.actions; @@ -4659,7 +4704,7 @@ async function checkRuleHasNohupSsh(rule) { // 方式1: 动作本身是 ssh_cmd_ref 类型(兼容两种 API 返回格式) // rules.get 返回 action.cmd_id(直接字段),actions.get 返回 action.ssh_ref.cmd_id(嵌套) - if (action.type === 'ssh_cmd_ref' && (action.ssh_ref?.cmd_id || action.cmd_id)) { + if (!action.template_id && action.type === 'ssh_cmd_ref' && (action.ssh_ref?.cmd_id || action.cmd_id)) { sshCmdId = action.ssh_ref?.cmd_id || action.cmd_id; } // 方式2: 动作有 template_id,需要查询模板获取实际类型 @@ -4667,21 +4712,23 @@ async function checkRuleHasNohupSsh(rule) { try { const tplResult = await api.call('automation.actions.get', { id: action.template_id }); if (tplResult.code === 0 && tplResult.data) { - if (tplResult.data.type === 'ssh_cmd_ref' && tplResult.data.ssh_ref?.cmd_id) { - sshCmdId = tplResult.data.ssh_ref.cmd_id; + if (tplResult.data.type === 'ssh_cmd_ref' && (tplResult.data.ssh_ref?.cmd_id || tplResult.data.cmd_id)) { + sshCmdId = tplResult.data.ssh_ref?.cmd_id || tplResult.data.cmd_id; } - } + } else return { unresolved: true }; } catch (e) { - // template fetch failed, skip + return { unresolved: true }; } } if (sshCmdId) { const cmdId = String(sshCmdId); + let foundCommand = false; // 在所有主机的命令中查找 for (const [hostId, cmds] of Object.entries(sshCommands)) { const cmd = cmds.find(c => String(c.id) === cmdId); if (cmd) { + foundCommand = true; if (cmd.nohup) { // 找到了 nohup 命令 // safeName:优先从 cmd.name 提取英文数字,fallback 到 cmd.id @@ -4691,12 +4738,6 @@ async function checkRuleHasNohupSsh(rule) { const pidFile = `/tmp/ts_nohup_${safeName}.pid`; const varName = cmd.varName || ''; // 服务模式变量名 - // 检测进程状态:多重 fallback 策略 - // 问题:nohup cmd & 的 $! 获取到的 PID 可能是中间 shell 进程, - // 真实主进程 PID 往往是 $! - 1(如 vLLM 等多进程服务) - // 策略:1) kill -0 PID 2) kill -0 PID-1 3) pgrep 按日志文件名兜底 - const checkCmd = `if [ -f ${pidFile} ]; then PID=$(cat ${pidFile}); if kill -0 $PID 2>/dev/null; then echo running; elif kill -0 $((PID-1)) 2>/dev/null; then echo running; else echo stopped; fi; else echo stopped; fi`; - return { logFile: logFile, pidFile: pidFile, @@ -4704,7 +4745,7 @@ async function checkRuleHasNohupSsh(rule) { progName: safeName, hostId: hostId, cmdName: cmd.name, - checkCmd: checkCmd, + commandId: cmdId, // 服务模式信息 serviceMode: cmd.serviceMode || false, varName: varName, @@ -4714,10 +4755,12 @@ async function checkRuleHasNohupSsh(rule) { } } } + if (!foundCommand) return { unresolved: true }; } } } catch (e) { console.error('checkRuleHasNohupSsh error:', e); + return { unresolved: true }; } return null; } @@ -4799,7 +4842,8 @@ async function quickActionRefreshLog(logFile, hostId) { if (!host) return; const contentEl = document.getElementById('quick-log-content'); - if (!contentEl) return; + if (!contentEl || document.hidden || contentEl.dataset.loading === 'true') return; + contentEl.dataset.loading = 'true'; try { const result = await api.call('ssh.exec', { @@ -4807,9 +4851,10 @@ async function quickActionRefreshLog(logFile, hostId) { port: host.port, user: host.username, keyid: host.keyid, - command: `if [ -f ${logFile} ]; then cat ${logFile}; else echo '${typeof t === 'function' ? t('automationPage.logFileEmptyBracket') : '[日志文件不存在或为空]'}'; fi`, + command: `if [ -f ${logFile} ]; then tail -c 60000 -- ${logFile}; else echo '${typeof t === 'function' ? t('automationPage.logFileEmptyBracket') : '[日志文件不存在或为空]'}'; fi`, timeout_ms: 15000 }); + if (!contentEl.isConnected || document.getElementById('quick-log-content') !== contentEl) return; if (result.code !== 0 || !result.data) { contentEl.textContent = (typeof t === 'function' ? t('automationPage.logFetchFailed') : '[获取失败]') + ' ' + (result.message || 'code=' + result.code); return; @@ -4822,9 +4867,12 @@ async function quickActionRefreshLog(logFile, hostId) { quickActionLastContent = output; } } catch (e) { + if (!contentEl.isConnected || document.getElementById('quick-log-content') !== contentEl) return; const _err = typeof t === 'function' ? t('automationPage.logError') : '[错误]'; const _retry = typeof t === 'function' ? t('automationPage.deviceBusyRetry') : '若设备繁忙可稍后重试。'; contentEl.textContent = _err + ' ' + e.message + '\n\n' + _retry; + } finally { + contentEl.dataset.loading = 'false'; } } @@ -4945,86 +4993,19 @@ function closeQuickLogModal() { * 快捷操作 - 终止进程(基于 PID 文件精确停止) * 支持杀进程组(vLLM 等多进程服务),SIGTERM → 等待 → SIGKILL 回退 */ -async function quickActionStopProcess(pidFile, hostId, cmdName, varName) { - const host = window._sshHostsData?.[hostId]; - if (!host) { - showToast((typeof t === 'function' ? t('sshPage.hostNotExistShort') : '主机不存在'), 'error'); - return; - } - - const confirmMsg = typeof t === 'function' ? t('toast.confirmTerminateCmd', { cmdName }) : `确定要终止 "${cmdName}" 吗?`; - if (!confirm(confirmMsg)) { - return; - } - +const serviceStopInFlight = new Set(); +async function quickActionStopProcess(commandId, automatic) { + if (serviceStopInFlight.has(commandId)) return; + if (!confirmAction(runtimeText(automatic ? 'confirmStopAutomatic' : 'confirmStop'))) return; + serviceStopInFlight.add(commandId); + for (const card of document.querySelectorAll('.quick-action-card')) + if (card.dataset.service === commandId) card.dataset.state = 'stopping'; try { - showToast((typeof t === 'function' ? t('toast.terminatingProcess') : '正在终止进程...'), 'info'); - - // 终止进程:支持 PID 和 PID-1 双重检测 - // 原因:nohup cmd & 的 $! 可能记录了中间 shell PID,真实主进程 PID = $! - 1 - // 逻辑:读取 PID 文件 → 找到活着的真实 PID → SIGTERM 进程组 → 等待 → SIGKILL 回退 - const killCmd = `if [ -f ${pidFile} ]; then ` + - `RAW_PID=$(cat ${pidFile}); ` + - // 确定真实 PID:先检查 RAW_PID,再检查 RAW_PID-1 - `if kill -0 $RAW_PID 2>/dev/null; then PID=$RAW_PID; ` + - `elif kill -0 $((RAW_PID-1)) 2>/dev/null; then PID=$((RAW_PID-1)); ` + - `else rm -f ${pidFile}; echo "ALREADY_STOPPED"; exit 0; fi; ` + - // 先尝试 SIGTERM 进程组(kill 负 PID),回退到单进程 kill - `kill -- -$PID 2>/dev/null; kill $PID 2>/dev/null; ` + - // 等待最多 3 秒 - `for i in 1 2 3 4 5 6; do sleep 0.5; kill -0 $PID 2>/dev/null || break; done; ` + - // 检查是否还活着 - `if kill -0 $PID 2>/dev/null; then ` + - // 仍在运行,SIGKILL 进程组 - `kill -9 -- -$PID 2>/dev/null; kill -9 $PID 2>/dev/null; ` + - `sleep 0.5; ` + - `if kill -0 $PID 2>/dev/null; then ` + - `echo "STILL_RUNNING"; ` + - `else ` + - `rm -f ${pidFile}; echo "FORCE_KILLED"; ` + - `fi; ` + - `else ` + - `rm -f ${pidFile}; echo "TERMINATED"; ` + - `fi; ` + - `else echo "NO_PID_FILE"; fi`; - - const result = await api.call('ssh.exec', { - host: host.host, - port: host.port, - user: host.username, - keyid: host.keyid, - command: killCmd, - timeout_ms: 15000 - }); - - if (result.code === 0 && result.data) { - const output = (result.data.stdout || '').trim(); - const msgMap = { - 'TERMINATED': typeof t === 'function' ? t('toast.terminateTERMINATED') : '服务已停止', - 'FORCE_KILLED': typeof t === 'function' ? t('toast.terminateFORCE_KILLED') : '服务已强制终止', - 'ALREADY_STOPPED': typeof t === 'function' ? t('toast.terminateALREADY_STOPPED') : '进程已不在运行,已清理 PID 文件', - 'NO_PID_FILE': typeof t === 'function' ? t('toast.terminateNO_PID_FILE') : 'PID 文件不存在', - 'STILL_RUNNING': typeof t === 'function' ? t('toast.terminateSTILL_RUNNING') : '无法终止进程,请手动处理' - }; - const msg = msgMap[output] || (output || (typeof t === 'function' ? t('toast.terminateDefault') : '操作完成')); - const isSuccess = ['TERMINATED', 'FORCE_KILLED', 'ALREADY_STOPPED'].includes(output); - showToast(msg, isSuccess ? 'success' : (output === 'STILL_RUNNING' ? 'error' : 'info')); - // 停止成功后,清除服务模式状态变量(否则"就绪"标签会残留) - if (isSuccess && varName) { - try { - await api.call('automation.variables.set', { name: `${varName}.status`, value: 'stopped' }); - } catch (e) { - console.warn('Failed to clear service status variable:', e); - } - } - // 刷新状态 - setTimeout(() => refreshQuickActions(), 1500); - } else { - showToast((result.message || (typeof t === 'function' ? t('common.operationFailed') : '操作失败')), 'error'); - } - } catch (e) { - showToast((typeof t === 'function' ? t('toast.errorMsg', { msg: e.message }) : '错误: ' + e.message), 'error'); - } + const result = await api.call('automation.services.stop', { command_id: commandId }); + const stopped = result.code === 0 && result.data?.state === 'stopped'; + showToast(runtimeText(stopped ? 'stopped' : 'outcomeUnknown'), stopped ? 'success' : 'warning'); + } catch (_) { showToast(runtimeText('outcomeUnknown'), 'warning'); } + finally { serviceStopInFlight.delete(commandId); await updateQuickActionServiceStatus(); } } // 时间同步功能 @@ -5139,18 +5120,15 @@ async function loadLedPage() { clearInterval(refreshInterval); // 取消系统页面的订阅 - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); - } const content = document.getElementById('page-content'); content.innerHTML = `
-

LED 控制

+

${t('nav.led')}

- - + +
@@ -5197,18 +5175,18 @@ async function refreshLedPage() { container.innerHTML = `
-

未找到 LED 设备

-

LED 设备可能尚未启动,请检查:

+

${t('ledPage.ledNotFound')}

+

${t('ledPage.ledNotStartedHint')}

    -
  • LED 服务状态 (service --status)
  • -
  • GPIO 引脚配置
  • +
  • ${t('promptRepair.ledServiceStatus')} (service --status)
  • +
  • ${t('ledPage.checkGpioConfig')}
`; } } catch (e) { console.error('LED list error:', e); - container.innerHTML = `
${typeof t === 'function' ? t('common.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message}
`; + container.innerHTML = `
${escapeHtml(typeof t === 'function' ? t('common.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message)}
`; } } @@ -5265,7 +5243,7 @@ function generateLedDeviceCard(dev) { ${dev.name} ${description}
-
${statusText}
+
${escapeHtml(statusText)}
@@ -5284,7 +5262,7 @@ function generateLedDeviceCard(dev) {
-
+
- - - - - - - - - - + + + + + + + + + +
@@ -5318,7 +5296,7 @@ function generateLedDeviceCard(dev) { ${matrixFooterBtns} -
@@ -5341,10 +5319,10 @@ function updateBrightnessDisplay(device, value) { async function fillColorFromPicker(device, color) { try { - await api.ledFill(device, color); + requireApiSuccess(await api.ledFill(device, color), 'ledFill'); ledStates[device] = true; updateLedCardState(device, true); - showToast(typeof t === 'function' ? t('toast.ledFilled', { device, color }) : `${device} 已填充 ${color}`, 'success'); + showToast(typeof t === 'function' ? t('toast.ledFilled', { device: getDeviceDescription(device), color }) : `${device} 已填充 ${color}`, 'success'); } catch (e) { showToast(typeof t === 'function' ? t('toast.ledFillFailed') + ': ' + e.message : `填充失败: ${e.message}`, 'error'); } @@ -5354,10 +5332,10 @@ async function quickFillColor(device, color) { const picker = document.getElementById(`color-picker-${device}`); if (picker) picker.value = color; try { - await api.ledFill(device, color); + requireApiSuccess(await api.ledFill(device, color), 'ledFill'); ledStates[device] = true; updateLedCardState(device, true, null); - showToast(typeof t === 'function' ? t('toast.ledFilled', { device, color }) : `${device} → ${color}`, 'success'); + showToast(typeof t === 'function' ? t('toast.ledFilled', { device: getDeviceDescription(device), color }) : `${device} → ${color}`, 'success'); } catch (e) { showToast(typeof t === 'function' ? t('toast.ledFillFailed') + ': ' + e.message : `填充失败: ${e.message}`, 'error'); } @@ -5365,11 +5343,11 @@ async function quickFillColor(device, color) { async function quickStartEffect(device, effect) { try { - await api.ledEffectStart(device, effect, { speed: 50 }); + requireApiSuccess(await api.ledEffectStart(device, effect, { speed: 50 }), 'ledEffectStart'); selectedEffects[device] = effect; ledStates[device] = true; updateLedCardState(device, true, effect); - showToast(typeof t === 'function' ? t('toast.ledEffectStarted', { device, effect }) : `${device}: ${effect}`, 'success'); + showToast(typeof t === 'function' ? t('toast.ledEffectStarted', { device: getDeviceDescription(device), effect }) : `${device}: ${effect}`, 'success'); } catch (e) { showToast(typeof t === 'function' ? t('toast.ledEffectStartFailed') + ': ' + e.message : `启动失败: ${e.message}`, 'error'); } @@ -5377,16 +5355,18 @@ async function quickStartEffect(device, effect) { async function allLedsOff() { const devices = window.ledDevicesCache || []; + let success = 0; const failures = []; for (const dev of devices) { try { - await api.ledClear(dev.name); + requireApiSuccess(await api.ledClear(dev.name), 'ledClear'); + success++; ledStates[dev.name] = false; updateLedCardState(dev.name, false); } catch (e) { - console.error(`关闭 ${dev.name} 失败:`, e); + failures.push({path: dev.name, message: e.message}); } } - showToast((typeof t === 'function' ? t('toast.allLedsOff') : '全部 LED 已关闭'), 'success'); + showOperationSummary('promptRepair.ledSummary', success, failures); } function updateLedCardState(device, isOn, effect = undefined) { @@ -5421,13 +5401,13 @@ function updateLedCardState(device, isOn, effect = undefined) { const powerIcon = powerBtn.querySelector('.power-icon'); if (isOn) { powerBtn.classList.add('on'); - powerBtn.title = '点击关闭'; + powerBtn.title = t('ledPage.clickOff'); if (powerIcon) { powerIcon.className = 'power-icon ri-lightbulb-fill'; } } else { powerBtn.classList.remove('on'); - powerBtn.title = '点击开启'; + powerBtn.title = t('ledPage.clickOn'); if (powerIcon) { powerIcon.className = 'power-icon ri-lightbulb-line'; } @@ -5459,7 +5439,7 @@ function openColorModal(device) { const title = document.getElementById('led-modal-title'); const body = document.getElementById('led-modal-body'); - title.textContent = `${device} - ${typeof t === 'function' ? t('ledPage.colorSettings') : '颜色设置'}`; + title.textContent = `${device} - ${typeof t === 'function' ? t('ui.colorSettings') : '颜色设置'}`; body.innerHTML = ` -
${client.is_static ? '静态' : '动态'}
+
${client.is_static ? t('networkPage.static') : t('networkPage.dynamic')}
`).join(''); } } catch (e) { - container.innerHTML = `
获取失败: ${e.message}
`; + if (!pageCurrent()) return; + container.innerHTML = `
${t('toast.fetchFailed')}: ${escapeHtml(e.message)}
`; } } @@ -8125,10 +8124,10 @@ async function toggleNat() { try { const status = await api.natStatus(); if (status.data?.enabled) { - await api.natDisable(); + requireApiSuccess(await api.natDisable(), 'natDisable'); showToast(typeof t === 'function' ? t('toast.natDisabled') : 'NAT 已禁用', 'success'); } else { - await api.natEnable(); + requireApiSuccess(await api.natEnable(), 'natEnable'); showToast(typeof t === 'function' ? t('toast.natEnabled') : 'NAT 已启用', 'success'); } await refreshNetworkPage(); @@ -8139,7 +8138,7 @@ async function toggleNat() { async function saveNatConfig() { try { - await api.natSave(); + requireApiSuccess(await api.natSave(), 'natSave'); showToast(typeof t === 'function' ? t('toast.natConfigSaved') : 'NAT 配置已保存', 'success'); } catch (e) { showToast((typeof t === 'function' ? t('toast.saveFailed') : '保存失败') + ': ' + e.message, 'error'); @@ -8153,12 +8152,10 @@ async function saveNatConfig() { let currentFilePath = '/sdcard'; async function loadFilesPage() { + const pageCurrent = capturePageValidity(); clearInterval(refreshInterval); // 取消系统页面的订阅 - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); - } const content = document.getElementById('page-content'); content.innerHTML = ` @@ -8258,6 +8255,7 @@ async function loadFilesPage() { selectedFiles.clear(); await refreshFilesPage(); + if (!pageCurrent()) return; } // 批量选择相关 @@ -8315,6 +8313,21 @@ function clearSelection() { updateSelectionUI(); } +function showOperationSummary(key, success, failures, extra = {}) { + const message = t(key, {success, fail: failures.length, ...extra}); + showToast(message, failures.length ? (success ? 'warning' : 'error') : extra.invalid ? 'warning' : 'success', 7000); + let panel = document.getElementById('operation-summary'); + if (!panel) { + panel = document.createElement('div'); + panel.id = 'operation-summary'; + panel.setAttribute('role', 'status'); + document.querySelector('main').appendChild(panel); + } + panel.style.whiteSpace = 'pre-wrap'; + panel.textContent = message + (failures.length ? '\n' + failures.map(f => f.path + ': ' + f.message).join('\n') : ''); + return {success, failures}; +} + async function batchDelete() { if (selectedFiles.size === 0) { showToast((typeof t === 'function' ? t('toast.selectFileToDelete') : '请先选择要删除的文件'), 'warning'); @@ -8322,34 +8335,28 @@ async function batchDelete() { } const count = selectedFiles.size; - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteFiles', { count }) : `确定要删除选中的 ${count} 个文件/文件夹吗?此操作不可撤销!`)) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmDeleteFiles', { count }) : `确定要删除选中的 ${count} 个文件/文件夹吗?此操作不可撤销!`)) { return; } - showToast(typeof t === 'function' ? t('files.deletingItems', { count }) : `正在删除 ${count} 个项目...`, 'info'); + showToast(typeof t === 'function' ? t('toast.deletingItems', { count }) : `正在删除 ${count} 个项目...`, 'info'); let successCount = 0; - let failCount = 0; + const failures = []; for (const path of selectedFiles) { try { - await api.storageDelete(path); + requireApiSuccess(await api.storageDelete(path), 'storageDelete'); successCount++; } catch (e) { console.error('Delete failed:', path, e); - failCount++; + failures.push({path, message: e.message}); } } selectedFiles.clear(); - - if (failCount === 0) { - showToast(typeof t === 'function' ? t('files.deleteSuccessCount', { count: successCount }) : `成功删除 ${successCount} 个项目`, 'success'); - } else { - showToast(typeof t === 'function' ? t('files.deletePartial', { success: successCount, fail: failCount }) : `删除完成: ${successCount} 成功, ${failCount} 失败`, 'warning'); - } - await refreshFilesPage(); + return showOperationSummary('promptRepair.deleteSummary', successCount, failures); } async function batchDownload() { @@ -8372,27 +8379,23 @@ async function batchDownload() { return; } - showToast(typeof t === 'function' ? t('files.downloadingFiles', { count: filesToDownload.length }) : `正在下载 ${filesToDownload.length} 个文件...`, 'info'); + showToast(typeof t === 'function' ? t('toast.downloadingFiles', { count: filesToDownload.length }) : `正在下载 ${filesToDownload.length} 个文件...`, 'info'); - // 逐个下载文件 + let success = 0; + const failures = []; for (const path of filesToDownload) { - try { - await downloadFile(path); - // 添加短暂延迟,避免浏览器阻止多个下载 - await new Promise(resolve => setTimeout(resolve, 300)); - } catch (e) { - console.error('Download failed:', path, e); - } + const result = await downloadFile(path, true); + if (result.started) success++; + else failures.push({path, message: result.error.message}); } - - showToast((typeof t === 'function' ? t('toast.batchDownloadComplete') : '批量下载完成'), 'success'); + return showOperationSummary('promptRepair.downloadSummary', success, failures); } // SD 卡挂载/卸载 async function mountSdCard() { try { showToast(typeof t === 'function' ? t('filePage.mountingSd') : '正在挂载 SD 卡...', 'info'); - await api.storageMount(); + requireApiSuccess(await api.storageMount(), 'storageMount'); showToast(typeof t === 'function' ? t('filePage.mountSdSuccess') : 'SD 卡挂载成功', 'success'); await refreshFilesPage(); } catch (e) { @@ -8401,13 +8404,13 @@ async function mountSdCard() { } async function unmountSdCard() { - if (!confirm(typeof t === 'function' ? t('filePage.confirmUnmountSd') : '确定要卸载 SD 卡吗?\n\n卸载后将无法访问 SD 卡上的文件。')) { + if (!confirmAction(typeof t === 'function' ? t('filePage.confirmUnmountSd') : '确定要卸载 SD 卡吗?\n\n卸载后将无法访问 SD 卡上的文件。')) { return; } try { showToast(typeof t === 'function' ? t('filePage.unmountingSd') : '正在卸载 SD 卡...', 'info'); - await api.storageUnmount(); + requireApiSuccess(await api.storageUnmount(), 'storageUnmount'); showToast(typeof t === 'function' ? t('filePage.unmountSdSuccess') : 'SD 卡已卸载', 'success'); if (currentFilePath.startsWith('/sdcard')) { currentFilePath = '/spiffs'; @@ -8419,14 +8422,23 @@ async function unmountSdCard() { } async function refreshFilesPage() { - await loadDirectory(currentFilePath); + const pageCurrent = capturePageValidity(); + const result = await loadDirectory(currentFilePath); + if (!pageCurrent()) return; + if (result?.stale) return result; await loadStorageStatus(); + if (!pageCurrent()) return; + return result; } +let directoryGeneration = 0; async function loadDirectory(path) { + const generation = ++directoryGeneration; currentFilePath = path; const listContainer = document.getElementById('file-list'); + const current = () => generation === directoryGeneration && currentFilePath === path && document.getElementById('file-list') === listContainer; + if (!listContainer) return {stale: true}; // 移除旧的事件监听器 listContainer.removeEventListener('click', handleFileListClick); @@ -8435,7 +8447,8 @@ async function loadDirectory(path) { // 如果是 SD 卡路径,先检查挂载状态,避免不必要的错误请求 if (path.startsWith('/sdcard')) { try { - const status = await api.storageStatus(); + const status = requireApiSuccess(await api.storageStatus(), 'storage.status'); + if (!current()) return {stale: true}; if (!status.data?.sd?.mounted) { console.log('SD card not mounted, showing mount prompt'); listContainer.innerHTML = ` @@ -8448,13 +8461,15 @@ async function loadDirectory(path) { return; } } catch (e) { + if (!current()) return {stale: true}; console.warn('Failed to check storage status:', e.message); // 继续尝试加载目录,让后续逻辑处理错误 } } try { - const result = await api.storageList(path); + const result = requireApiSuccess(await api.storageList(path), 'storage.list'); + if (!current()) return {stale: true}; console.log('storageList result:', result); const entries = result.data?.entries || []; @@ -8512,7 +8527,7 @@ async function loadDirectory(path) { ${entry.name} ${size} - ${entry.type !== 'dir' ? `` : ''} + ${entry.type !== 'dir' ? `` : ''} `; }).join('')} @@ -8523,11 +8538,12 @@ async function loadDirectory(path) { // 使用事件委托处理点击 listContainer.addEventListener('click', handleFileListClick); } catch (e) { + if (!current()) return {stale: true}; console.error('loadDirectory error:', e); // 检查是否是 SD 卡未挂载(后端返回 'SD card not mounted' 或 'Directory not found') const isUnmounted = path.startsWith('/sdcard') && - (e.message.includes('not mounted') || e.message.includes('未挂载') || e.message.includes('Directory not found')); + (e.message.includes('not mounted') || e.message.includes(t('filePage.notMounted')) || e.message.includes('Directory not found')); if (isUnmounted) { listContainer.innerHTML = ` @@ -8537,9 +8553,11 @@ async function loadDirectory(path) {
`; } else { - listContainer.innerHTML = '
' + (typeof t === 'function' ? t('filePage.loadFailed') : '加载失败') + ': ' + e.message + '
'; + listContainer.textContent = t('promptRepair.listRefreshFailed') + '\n' + e.message; } + return {error: e}; } + return {refreshed: true}; } // 事件委托处理文件列表点击 @@ -8576,9 +8594,13 @@ function handleFileListClick(e) { } } +let storageStatusGeneration = 0; async function loadStorageStatus() { + const generation = ++storageStatusGeneration; + const pageCurrent = capturePageValidity(); try { const status = await api.storageStatus(); + if (!pageCurrent() || generation !== storageStatusGeneration) return; const container = document.getElementById('storage-status'); const controlsContainer = document.getElementById('storage-controls'); @@ -8613,6 +8635,7 @@ async function loadStorageStatus() { } } } catch (e) { + if (!pageCurrent() || generation !== storageStatusGeneration) return; console.log('Storage status error:', e); } } @@ -8652,8 +8675,12 @@ function formatFileSize(bytes) { // 上传相关 let filesToUpload = []; +let uploadGeneration = 0; +const uploadPathVersions = new Map(); +const uploadPendingPaths = new Map(); function showUploadDialog() { + uploadGeneration++; filesToUpload = []; document.getElementById('upload-list').innerHTML = ''; document.getElementById('upload-modal').classList.remove('hidden'); @@ -8690,13 +8717,16 @@ function handleFileSelect(event) { filesToUpload = filesToUpload.concat(files); const listContainer = document.getElementById('upload-list'); - listContainer.innerHTML = filesToUpload.map((f, i) => ` -
- ${f.name} - ${formatFileSize(f.size)} - -
- `).join(''); + listContainer.replaceChildren(); + filesToUpload.forEach((file, index) => { + const row = document.createElement('div'); row.className = 'upload-item'; + const name = document.createElement('span'); name.textContent = file.name; + const state = document.createElement('span'); state.textContent = formatFileSize(file.size); + const remove = document.createElement('button'); remove.className = 'btn btn-sm'; + remove.textContent = '×'; remove.setAttribute('aria-label', t('common.delete')); + remove.onclick = () => removeUploadFile(index); + row.append(name, state, remove); listContainer.appendChild(row); + }); } function removeUploadFile(index) { @@ -8705,60 +8735,73 @@ function removeUploadFile(index) { } async function uploadFiles() { - if (filesToUpload.length === 0) { - showToast((typeof t === 'function' ? t('toast.selectFileToUpload') : '请选择要上传的文件'), 'warning'); - return; - } - - const listContainer = document.getElementById('upload-list'); - - for (let i = 0; i < filesToUpload.length; i++) { - const file = filesToUpload[i]; - const targetPath = currentFilePath + '/' + file.name; - - // 更新状态 - const items = listContainer.querySelectorAll('.upload-item'); - if (items[i]) { - items[i].innerHTML = `${file.name}${typeof t === 'function' ? t('common.uploading') : '上传中...'}`; - } - + if (!filesToUpload.length) { showToast(t('toast.selectFileToUpload'), 'warning'); return; } + const generation = ++uploadGeneration; + const destination = currentFilePath; + const pageCurrent = capturePageValidity(); + const list = document.getElementById('upload-list'); + const page = document.getElementById('page-content'); + const files = [...filesToUpload]; + const items = [...list.querySelectorAll('.upload-item')]; + const failures = []; + let success = 0, invalid = 0; + // Invalidate every old entry before starting the first request. + for (const row of items) while (row.children.length > 3) row.children[3].remove(); + const versions = files.map(file => { + const path = destination + '/' + file.name; + const version = {contended: false}; + uploadPathVersions.set(path, version); + return version; + }); + for (const [index, file] of files.entries()) { + const path = destination + '/' + file.name; + const row = items[index]; + const current = () => generation === uploadGeneration && + document.getElementById('upload-list') === list && [...list.children].includes(row) && + uploadPathVersions.get(path) === versions[index]; + const state = row?.children[1]; + if (current() && state) state.textContent = t('files.uploading'); + const pending = uploadPendingPaths.get(path) || new Set(); + if (pending.size) { + versions[index].contended = true; + for (const version of pending) version.contended = true; + } + pending.add(versions[index]); uploadPendingPaths.set(path, pending); try { - console.log('Uploading file:', targetPath); - const result = await api.fileUpload(targetPath, file); - console.log('Upload result:', result); - if (items[i]) { - items[i].innerHTML = `${file.name}${typeof t === 'function' ? t('fileManager.uploadComplete') : '完成'}`; - } - - // 检查是否是配置包上传,显示验证结果 - if (result.config_pack) { - const pack = result.config_pack; - if (pack.valid) { - const signer = pack.signature?.signer_cn || '未知'; - const isOfficial = pack.signature?.is_official ? '(官方)' : ''; - showToast(typeof t === 'function' ? t('toast.configPackVerifySuccess', { signer, isOfficial }) : `配置包验证成功\n签名者: ${signer} ${isOfficial}`, 'success', 5000); - - // 显示应用确认对话框 - setTimeout(() => { - showConfigPackApplyConfirm(targetPath, pack); - }, 500); - } else { - showToast(typeof t === 'function' ? t('toast.configPackVerifyFailed', { msg: pack.result_message }) : `配置包验证失败: ${pack.result_message}`, 'error', 5000); - } - } - } catch (e) { - console.error('Upload error:', e); - if (items[i]) { - items[i].innerHTML = `${file.name}${typeof t === 'function' ? t('common.uploadFailedMsg', { msg: e.message }) : '失败: ' + e.message}`; + const result = await api.fileUpload(path, file); + success++; + const pack = result.config_pack; + if (pack && pack.valid !== true) invalid++; + if (!current()) continue; + if (state) state.textContent = t('promptRepair.uploaded'); + if (pack?.valid === true && versions[index].contended) { + invalid++; + if (state) state.textContent = t('promptRepair.packRevalidate'); + } else if (pack?.valid === true) { + if (state) state.textContent = t('promptRepair.packVerified'); + const apply = document.createElement('button'); + apply.className = 'btn'; apply.textContent = t('common.apply'); + const verified = () => current() && !versions[index].contended; + apply.onclick = () => { if (verified()) showConfigPackApplyConfirm(path, pack, verified); }; + row.appendChild(apply); + } else if (pack && state) { + state.textContent = t('promptRepair.packInvalid') + '\n' + apiErrorMessage({error: pack.result_message}); } - } + } catch (error) { + failures.push({path, message: error.message}); + if (current() && state) state.textContent = error.message; + } finally { + pending.delete(versions[index]); + if (!pending.size) uploadPendingPaths.delete(path); + } + } + if (generation !== uploadGeneration) return {success, failures}; + const summary = showOperationSummary('promptRepair.uploadSummary', success, failures, {invalid}); + // Refresh is a separate read: its failure must never change confirmed upload results. + if (success && pageCurrent() && document.getElementById('page-content') === page && currentFilePath === destination && document.getElementById('file-list')) { + await refreshFilesPage(); } - - showToast((typeof t === 'function' ? t('toast.uploadComplete') : '上传完成'), 'success'); - setTimeout(() => { - closeUploadDialog(); - refreshFilesPage(); - }, 1000); + return summary; } // 新建文件夹 @@ -8780,7 +8823,7 @@ async function createNewFolder() { const path = currentFilePath + '/' + name; try { - await api.storageMkdir(path); + requireApiSuccess(await api.storageMkdir(path), 'storageMkdir'); showToast((typeof t === 'function' ? t('toast.folderCreated') : '文件夹创建成功'), 'success'); closeNewFolderDialog(); refreshFilesPage(); @@ -8815,7 +8858,7 @@ async function doRename() { const newPath = pathParts.join('/') + '/' + newName; try { - await api.storageRename(originalPath, newPath); + requireApiSuccess(await api.storageRename(originalPath, newPath), 'storageRename'); showToast((typeof t === 'function' ? t('toast.renameSuccess') : '重命名成功'), 'success'); closeRenameDialog(); refreshFilesPage(); @@ -8825,39 +8868,37 @@ async function doRename() { } // 下载文件 -async function downloadFile(path) { - console.log('Downloading file:', path); +async function downloadFile(path, silent = false) { + let url; + let anchor; try { const blob = await api.fileDownload(path); - console.log('Download blob:', blob); - const filename = path.split('/').pop(); - - // 创建下载链接 - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = filename; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - - showToast((typeof t === 'function' ? t('toast.downloadStart') : '下载开始'), 'success'); - } catch (e) { - console.error('Download error:', e); - showToast((typeof t === 'function' ? t('toast.downloadFailedMsg', { msg: e.message }) : '下载失败: ' + e.message), 'error'); + url = URL.createObjectURL(blob); + anchor = document.createElement('a'); + anchor.href = url; + anchor.download = path.split('/').pop(); + document.body.appendChild(anchor); + anchor.click(); + if (!silent) showToast(t('promptRepair.downloadStarted'), 'success'); + return {started: true}; + } catch (error) { + if (!silent) showToast(t('toast.downloadFailedMsg', {msg: error.message}), 'error'); + return {started: false, error}; + } finally { + if (anchor) anchor.remove(); + if (url) setTimeout(() => URL.revokeObjectURL(url), 1000); } } // 删除文件 async function deleteFile(path) { const name = path.split('/').pop(); - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteItem', { name }) : `确定要删除 "${name}" 吗?`)) { + if (!confirmAction(typeof t === 'function' ? t('common.confirmDeleteItem', { name }) : `确定要删除 "${name}" 吗?`)) { return; } try { - await api.storageDelete(path); + requireApiSuccess(await api.storageDelete(path), 'storageDelete'); showToast((typeof t === 'function' ? t('toast.deleteSuccess') : '删除成功'), 'success'); refreshFilesPage(); } catch (e) { @@ -8871,58 +8912,58 @@ async function deleteFile(path) { // 模块描述信息 const CONFIG_MODULE_INFO = { - net: { name: '网络', icon: 'ri-global-line', description: '以太网和主机名配置' }, - dhcp: { name: 'DHCP', icon: 'ri-router-line', description: 'DHCP 服务器配置' }, - wifi: { name: 'WiFi', icon: 'ri-wifi-line', description: 'WiFi AP 配置' }, - led: { name: 'LED', icon: 'ri-lightbulb-line', description: 'LED 亮度和效果配置' }, - fan: { name: '风扇', icon: 'ri-tornado-line', description: '风扇控制配置' }, - device: { name: '设备', icon: 'ri-computer-line', description: 'AGX 设备控制配置' }, - system: { name: '系统', icon: 'ri-settings-line', description: '系统和控制台配置' } + net: { get name() { return t('nav.network'); }, icon: 'ri-global-line', get description() { return t('configPage.moduleNetDesc'); } }, + dhcp: { name: 'DHCP', icon: 'ri-router-line', get description() { return t('configPage.moduleDhcpDesc'); } }, + wifi: { name: 'WiFi', icon: 'ri-wifi-line', get description() { return t('configPage.moduleWifiDesc'); } }, + led: { name: 'LED', icon: 'ri-lightbulb-line', get description() { return t('configPage.moduleLedDesc'); } }, + fan: { get name() { return t('automation.fan'); }, icon: 'ri-tornado-line', get description() { return t('configPage.moduleFanDesc'); } }, + device: { get name() { return t('common.devices'); }, icon: 'ri-computer-line', get description() { return t('configPage.moduleDeviceDesc'); } }, + system: { get name() { return t('nav.system'); }, icon: 'ri-settings-line', get description() { return t('configPage.moduleSystemDesc'); } } }; // 配置项的用户友好描述 const CONFIG_KEY_LABELS = { // net - 'eth.enabled': { label: '以太网启用', type: 'bool' }, - 'eth.dhcp': { label: 'DHCP 客户端', type: 'bool' }, - 'eth.ip': { label: 'IP 地址', type: 'ip' }, - 'eth.netmask': { label: '子网掩码', type: 'ip' }, - 'eth.gateway': { label: '网关', type: 'ip' }, - 'hostname': { label: '主机名', type: 'string' }, + 'eth.enabled': { get label() { return t('configPage.ethEnabled'); }, type: 'bool' }, + 'eth.dhcp': { get label() { return t('network.dhcpClients'); }, type: 'bool' }, + 'eth.ip': { get label() { return t('system.ipAddress'); }, type: 'ip' }, + 'eth.netmask': { get label() { return t('network.subnetMask'); }, type: 'ip' }, + 'eth.gateway': { get label() { return t('network.gateway'); }, type: 'ip' }, + 'hostname': { get label() { return t('network.hostname'); }, type: 'string' }, // dhcp - 'enabled': { label: '启用', type: 'bool' }, - 'start_ip': { label: '起始 IP', type: 'ip' }, - 'end_ip': { label: '结束 IP', type: 'ip' }, - 'lease_time': { label: '租约时间 (秒)', type: 'number' }, + 'enabled': { get label() { return t('common.enable'); }, type: 'bool' }, + 'start_ip': { get label() { return t('configPage.startIp'); }, type: 'ip' }, + 'end_ip': { get label() { return t('configPage.endIp'); }, type: 'ip' }, + 'lease_time': { get label() { return t('configPage.leaseTime'); }, type: 'number' }, // wifi - 'mode': { label: '模式', type: 'select', options: ['off', 'ap', 'sta', 'apsta'] }, + 'mode': { get label() { return t('network.mode'); }, type: 'select', options: ['off', 'ap', 'sta', 'apsta'] }, 'ap.ssid': { label: 'AP SSID', type: 'string' }, - 'ap.password': { label: 'AP 密码', type: 'password' }, - 'ap.channel': { label: 'AP 信道', type: 'number', min: 1, max: 13 }, - 'ap.max_conn': { label: '最大连接数', type: 'number', min: 1, max: 10 }, - 'ap.hidden': { label: '隐藏 SSID', type: 'bool' }, + 'ap.password': { get label() { return t('configPage.apPassword'); }, type: 'password' }, + 'ap.channel': { get label() { return t('configPage.apChannel'); }, type: 'number', min: 1, max: 13 }, + 'ap.max_conn': { get label() { return t('network.maxConnections'); }, type: 'number', min: 1, max: 10 }, + 'ap.hidden': { get label() { return t('networkPage.hideSSID'); }, type: 'bool' }, // led - 'brightness': { label: '亮度', type: 'number', min: 0, max: 255 }, - 'effect_speed': { label: '效果速度', type: 'number', min: 1, max: 100 }, - 'power_on_effect': { label: '开机效果', type: 'string' }, - 'idle_effect': { label: '待机效果', type: 'string' }, + 'brightness': { get label() { return t('led.brightness'); }, type: 'number', min: 0, max: 255 }, + 'effect_speed': { get label() { return t('configPage.effectSpeed'); }, type: 'number', min: 1, max: 100 }, + 'power_on_effect': { get label() { return t('configPage.powerOnEffect'); }, type: 'string' }, + 'idle_effect': { get label() { return t('configPage.idleEffect'); }, type: 'string' }, // fan - 'min_duty': { label: '最小占空比 (%)', type: 'number', min: 0, max: 100 }, - 'max_duty': { label: '最大占空比 (%)', type: 'number', min: 0, max: 100 }, - 'target_temp': { label: '目标温度 (°C)', type: 'number', min: 20, max: 80 }, + 'min_duty': { get label() { return t('configPage.minDuty'); }, type: 'number', min: 0, max: 100 }, + 'max_duty': { get label() { return t('configPage.maxDuty'); }, type: 'number', min: 0, max: 100 }, + 'target_temp': { get label() { return t('configPage.targetTemp'); }, type: 'number', min: 20, max: 80 }, // device - 'agx.auto_power_on': { label: 'AGX 自动开机', type: 'bool' }, - 'agx.power_on_delay': { label: '开机延迟 (ms)', type: 'number' }, - 'agx.force_off_timeout': { label: '强制关机超时 (ms)', type: 'number' }, - 'monitor.enabled': { label: '监控启用', type: 'bool' }, - 'monitor.interval': { label: '监控间隔 (ms)', type: 'number' }, + 'agx.auto_power_on': { get label() { return t('configPage.agxAutoPowerOn'); }, type: 'bool' }, + 'agx.power_on_delay': { get label() { return t('configPage.powerOnDelay'); }, type: 'number' }, + 'agx.force_off_timeout': { get label() { return t('configPage.forceOffTimeout'); }, type: 'number' }, + 'monitor.enabled': { get label() { return t('configPage.monitorEnabled'); }, type: 'bool' }, + 'monitor.interval': { get label() { return t('configPage.monitorInterval'); }, type: 'number' }, // system - 'timezone': { label: '时区', type: 'string' }, - 'log_level': { label: '日志级别', type: 'select', options: ['none', 'error', 'warn', 'info', 'debug', 'verbose'] }, - 'console.enabled': { label: '控制台启用', type: 'bool' }, - 'console.baudrate': { label: '波特率', type: 'select', options: [9600, 115200, 460800, 921600] }, - 'webui.enabled': { label: 'WebUI 启用', type: 'bool' }, - 'webui.port': { label: 'WebUI 端口', type: 'number', min: 1, max: 65535 } + 'timezone': { get label() { return t('common.timezone'); }, type: 'string' }, + 'log_level': { get label() { return t('configPage.logLevel'); }, type: 'select', options: ['none', 'error', 'warn', 'info', 'debug', 'verbose'] }, + 'console.enabled': { get label() { return t('configPage.consoleEnabled'); }, type: 'bool' }, + 'console.baudrate': { get label() { return t('configPage.baudrate'); }, type: 'select', options: [9600, 115200, 460800, 921600] }, + 'webui.enabled': { get label() { return t('configPage.webuiEnabled'); }, type: 'bool' }, + 'webui.port': { get label() { return t('configPage.webuiPort'); }, type: 'number', min: 1, max: 65535 } }; // ========================================================================= @@ -8941,8 +8982,10 @@ let sshCommands = {}; * - 旧格式(兼容): "cmd_xxxxxxxx" (随机 hex) */ async function loadSshCommands() { + const pageCurrent = capturePageValidity(); try { const result = await api.call('ssh.commands.list', {}); + if (!pageCurrent()) return; if (result && result.data && result.data.commands) { // 按 host_id 组织 sshCommands = {}; @@ -9009,6 +9052,7 @@ async function loadSshCommands() { } } } catch (e) { + if (!pageCurrent()) return; console.error('Failed to load SSH commands from backend:', e); sshCommands = {}; } @@ -9049,7 +9093,7 @@ async function saveSshCommandToBackend(hostId, cmdData, cmdId) { if (result && result.code === 0 && result.data && result.data.id) { return result.data.id; } - throw new Error(result?.message || 'Failed to save command'); + throw new ApiOperationError(result, 'ssh.commands.add'); } /** @@ -9057,7 +9101,7 @@ async function saveSshCommandToBackend(hostId, cmdData, cmdId) { * @param {string} cmdId - 指令 ID(如 "AGX_Power_On" 或 "cmd_xxxxxxxx") */ async function deleteSshCommandFromBackend(cmdId) { - await api.call('ssh.commands.remove', { id: cmdId }); + requireApiSuccess(await api.call('ssh.commands.remove', { id: cmdId }), 'call'); } /** @@ -9068,7 +9112,7 @@ async function deleteSshCommandFromBackend(cmdId) { async function preCreateCommandVariables(varName) { // 后端 ssh.commands.add API 在保存时已自动创建变量 // 此函数保留作为兼容占位符 - console.debug(`Variables for ${varName}.* are managed by backend`); + console.debug(`Variables for ${escapeHtml(varName)}.* are managed by backend`); } /** @@ -9082,18 +9126,17 @@ async function ensureAllCommandVariables() { } async function loadCommandsPage() { + const pageCurrent = capturePageValidity(); clearInterval(refreshInterval); stopServiceStatusRefresh(); - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); - } // 重置执行状态(防止页面切换后状态残留) currentExecSessionId = null; // 加载已保存的指令(从后端) await loadSshCommands(); + if (!pageCurrent()) return; const content = document.getElementById('page-content'); content.innerHTML = ` @@ -9108,7 +9151,7 @@ async function loadCommandsPage() {
-
${t('ssh.loadingHosts')}
+
${t('sshPage.loadingHosts')}
@@ -9123,7 +9166,7 @@ async function loadCommandsPage() { `; } @@ -9771,7 +9817,8 @@ async function loadHostSelector() { refreshCommandsList(); } catch (e) { - container.innerHTML = `
加载失败: ${e.message}
`; + if (!pageCurrent()) return; + container.innerHTML = `
${t('common.loadFailed')}: ${escapeHtml(e.message)}
`; } } @@ -9810,7 +9857,7 @@ function refreshCommandsList() { const isOrphan = cmd.orphan === true; const orphanWarningHtml = isOrphan ? `
- 主机 "${escapeHtml(cmd.originalHostId || '?')}" 不存在,请删除或重新关联 + ${escapeHtml(t('promptRepair.orphanHost', {id: cmd.originalHostId || '?'}))}
` : ''; @@ -9818,9 +9865,9 @@ function refreshCommandsList() { const hasPatternsConfig = cmd.expectPattern || cmd.failPattern || cmd.extractPattern; const patternsHtml = hasPatternsConfig ? `
- ${cmd.expectPattern ? '' : ''} - ${cmd.failPattern ? '' : ''} - ${cmd.extractPattern ? '' : ''} + ${cmd.expectPattern ? '' : ''} + ${cmd.failPattern ? '' : ''} + ${cmd.extractPattern ? '' : ''}
` : ''; @@ -9831,20 +9878,20 @@ function refreshCommandsList() { // 服务模式:显示服务状态标签(无色块背景) // 使用 cmd.id 作为唯一标识,避免多个服务时 ID 冲突 const statusId = `service-status-${cmd.id || idx}`; - nohupHtml = `...`; + nohupHtml = `...`; } else { - nohupHtml = ''; + nohupHtml = (""); } } // 变量按钮(仅当设置了 varName 时显示) - const varBtnHtml = cmd.varName ? `` : ''; + const varBtnHtml = cmd.varName ? `` : ''; // 服务模式按钮(日志、停止) const safeName = cmd.name.replace(/[^a-zA-Z0-9]/g, '').slice(0, 20) || String(cmd.id).replace(/[^a-zA-Z0-9]/g, '').slice(0, 20) || 'cmd'; const serviceActionsHtml = (cmd.nohup && cmd.serviceMode) ? ` - - + + ` : ''; // 图标显示:支持 RemixIcon 类名、图片路径或旧版 Emoji @@ -9905,7 +9952,7 @@ async function updateServiceStatusInList() { } try { - const result = await api.call('automation.variables.get', { name: `${varName}.status` }); + const result = await api.call('automation.variables.get', { name: `${escapeHtml(varName)}.status` }); if (result && result.data && result.data.value !== undefined) { const status = result.data.value; @@ -9916,7 +9963,7 @@ async function updateServiceStatusInList() { statusEl.className = 'service-status status-idle'; } } catch (e) { - console.error(`[ServiceStatus] Error getting ${varName}.status:`, e); + console.error(`[ServiceStatus] Error getting ${escapeHtml(varName)}.status:`, e); statusEl.textContent = (typeof t === 'function' ? t('sshPage.statusUnknown') : '未知'); statusEl.className = 'service-status status-unknown'; } @@ -9927,13 +9974,9 @@ async function updateServiceStatusInList() { * 获取服务状态显示文本 */ function getServiceStatusLabel(status) { - if (typeof t !== 'function') { - const labels = { 'ready': '就绪', 'checking': '检测中', 'timeout': '超时', 'failed': '失败', 'idle': '未启动', 'stopped': '已停止' }; - return labels[status] || status; - } const keyMap = { 'ready': 'sshPage.statusReady', 'checking': 'sshPage.statusChecking', 'timeout': 'sshPage.statusTimeout', 'failed': 'sshPage.statusFailed', 'idle': 'sshPage.statusIdle', 'stopped': 'sshPage.statusStopped' }; const key = keyMap[status]; - return key ? t(key) : status; + return key ? t(key) : t('common.unknown'); } function showAddCommandModal() { @@ -10018,14 +10061,14 @@ async function showCommandVariables(varName) { // 更新标题 const header = modal.querySelector('.modal-header h2'); - if (header) header.textContent = typeof t === 'function' ? t('ui.commandVariablesWithName', { varName }) : `指令变量: ${varName}.*`; + if (header) header.textContent = typeof t === 'function' ? t('ui.commandVariablesWithName', { varName }) : `指令变量: ${escapeHtml(varName)}.*`; body.innerHTML = '
' + t('common.loading') + '
'; modal.classList.remove('hidden'); try { const result = await api.call('automation.variables.list', { - prefix: `${varName}.`, + prefix: `${escapeHtml(varName)}.`, include_meta: true }); if (result.code === 0 && result.data && result.data.variables) { @@ -10063,10 +10106,10 @@ async function showCommandVariables(varName) { `; } else { - body.innerHTML = `

${result.message || (typeof t === 'function' ? t('sshPage.getVarFailed') : '获取变量失败')}

`; + body.innerHTML = `

${escapeHtml(result.message || (typeof t === 'function' ? t('sshPage.getVarFailed') : '获取变量失败'))}

`; } } catch (error) { - body.innerHTML = `

${error.message}

`; + body.innerHTML = `

${escapeHtml(error.message)}

`; } } @@ -10172,7 +10215,7 @@ function switchCmdIconType(type) { // 更新 Tab 状态 document.querySelectorAll('.icon-type-tabs .icon-tab').forEach(tab => { - tab.classList.toggle('active', (type === 'emoji' && tab.textContent.includes('图标')) || (type === 'image' && tab.textContent.includes('图片'))); + tab.classList.toggle('active', (type === 'emoji' && tab.textContent.includes(t('automation.iconLabel'))) || (type === 'image' && tab.textContent.includes(t('automation.imageTab')))); }); // 切换面板显示 @@ -10258,13 +10301,13 @@ function validateCommandId(input) { let errorMsg = ''; if (hasInvalidChars) { - errorMsg = '只允许字母、数字、下划线、连字符'; + errorMsg = t('sshPage.idValidCharsOnly'); } else if (startsWithInvalid) { - errorMsg = '不能以 _ 或 - 开头'; + errorMsg = t('sshPage.idNoStartUnderscore'); } else if (endsWithInvalid) { - errorMsg = '不能以 _ 或 - 结尾'; + errorMsg = t('sshPage.idNoEndUnderscore'); } else if (value.length > 31) { - errorMsg = 'ID 过长(最多 31 个字符)'; + errorMsg = t('sshPage.idTooLong'); } if (errorMsg) { @@ -10403,7 +10446,7 @@ function editCommand(idx) { const cmd = sshCommands[selectedHostId]?.[idx]; if (!cmd) return; - document.getElementById('command-modal-title').textContent = typeof t === 'function' ? t('otaPage.editCommand') : '编辑指令'; + document.getElementById('command-modal-title').textContent = typeof t === 'function' ? t('ssh.editCommand') : '编辑指令'; /* 编辑模式:设置 ID 并标记为只读 */ const idInput = document.getElementById('cmd-edit-id'); @@ -10506,7 +10549,7 @@ async function exportSshCommand(cmdId) { showExportSshCommandModal(cmdId); } else { // 非开发机:直接使用设备证书加密,询问是否包含主机 - const includeHost = confirm(typeof t === 'function' ? t('automation.confirmExportWithHost') : '是否同时导出该指令依赖的主机配置?\n\n点击「确定」将主机配置一起打包(推荐),点击「取消」仅导出指令。'); + const includeHost = confirmAction(typeof t === 'function' ? t('ui.confirmExportWithHost') : '是否同时导出该指令依赖的主机配置?\n\n点击「确定」将主机配置一起打包(推荐),点击「取消」仅导出指令。'); await doExportSshCommand(cmdId, null, includeHost); } } @@ -10525,8 +10568,8 @@ function showExportSshCommandModal(cmdId) { modal.innerHTML = ` @@ -12288,9 +12324,11 @@ async function loadSecurityPage() { `; await refreshSecurityPage(); + if (!pageCurrent()) return; } async function refreshSecurityPage() { + const pageCurrent = capturePageValidity(); // 密钥列表 const tbody = document.getElementById('keys-table-body'); let allKeysHtml = ''; @@ -12299,6 +12337,7 @@ async function refreshSecurityPage() { // 1. 加载 SSH 密钥 try { const keys = await api.keyList(); + if (!pageCurrent()) return; const sshKeySelect = document.getElementById('ssh-keyid'); // 更新 SSH 测试的密钥下拉列表 @@ -12310,7 +12349,7 @@ async function refreshSecurityPage() { option.value = key.id; // 隐藏密钥显示别名或掩码 ID,否则显示真实 ID const displayName = (key.hidden && key.alias) ? key.alias : key.id; - option.textContent = `${key.hidden ? '[隐藏] ' : ''}${displayName} (${key.type_desc || key.type})`; + option.textContent = `${key.hidden ? t('promptRepair.hiddenPrefix') : ''}${displayName} (${key.type_desc || key.type})`; sshKeySelect.appendChild(option); }); } @@ -12345,12 +12384,14 @@ async function refreshSecurityPage() { }).join(''); } } catch (e) { + if (!pageCurrent()) return; console.error('加载 SSH 密钥失败:', e); } // 2. 加载 HTTPS 密钥(来自 ts_cert) try { const certStatus = await api.certStatus(); + if (!pageCurrent()) return; console.log('HTTPS cert status:', certStatus); if (certStatus.code === 0) { @@ -12400,6 +12441,7 @@ async function refreshSecurityPage() { } } } catch (e) { + if (!pageCurrent()) return; console.error('加载 HTTPS 密钥状态失败:', e); } @@ -12412,15 +12454,19 @@ async function refreshSecurityPage() { // SSH 已部署主机列表(加载数据并渲染到 DOM) await refreshSshHostsList(); + if (!pageCurrent()) return; // 已知主机指纹列表 await refreshKnownHostsList(); + if (!pageCurrent()) return; // HTTPS 证书状态 await refreshCertStatus(); + if (!pageCurrent()) return; // Config Pack 状态 await refreshConfigPackStatus(); + if (!pageCurrent()) return; } /** @@ -12430,21 +12476,26 @@ async function refreshSecurityPage() { * 仅加载 SSH hosts 数据到 window._sshHostsData(不渲染 DOM) */ async function loadSshHostsData() { + const pageCurrent = capturePageValidity(); try { const result = await api.call('ssh.hosts.list', {}); + if (!pageCurrent()) return; const hosts = result.data?.hosts || []; window._sshHostsData = {}; hosts.forEach(h => { window._sshHostsData[h.id] = h; }); console.log('loadSshHostsData: loaded', Object.keys(window._sshHostsData).length, 'hosts'); } catch (e) { + if (!pageCurrent()) return; console.error('loadSshHostsData error:', e); window._sshHostsData = {}; } } async function refreshSshHostsList() { + const pageCurrent = capturePageValidity(); // 首先加载 SSH hosts 数据(无需 DOM) await loadSshHostsData(); + if (!pageCurrent()) return; const tbody = document.getElementById('ssh-hosts-table-body'); if (!tbody) return; // DOM 渲染部分可选 @@ -12476,6 +12527,7 @@ async function refreshSshHostsList() { // 存储主机列表供索引访问 window._sshHostsList = hosts; } catch (e) { + if (!pageCurrent()) return; console.error('Refresh SSH hosts error:', e); tbody.innerHTML = `${typeof t === 'function' ? t('common.loadFailed') : '加载失败'}`; } @@ -12485,11 +12537,13 @@ async function refreshSshHostsList() { * 刷新已知主机指纹列表 */ async function refreshKnownHostsList() { + const pageCurrent = capturePageValidity(); const tbody = document.getElementById('known-hosts-table-body'); if (!tbody) return; try { const result = await api.call('hosts.list', {}); + if (!pageCurrent()) return; const hosts = result.data?.hosts || []; if (hosts.length === 0) { @@ -12514,6 +12568,7 @@ async function refreshKnownHostsList() { `).join(''); } catch (e) { + if (!pageCurrent()) return; console.error('Refresh known hosts error:', e); tbody.innerHTML = `${typeof t === 'function' ? t('common.loadFailed') : 'Load failed'}`; } @@ -12536,7 +12591,7 @@ async function removeKnownHost(index) { const host = window._knownHostsList?.[index]; if (!host) return; - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteFingerprint', { host: host.host, port: host.port }) : `确定要删除主机 ${host.host}:${host.port} 的指纹记录吗?\n\n删除后下次连接将重新验证服务器指纹。`)) return; + if (!confirmAction(typeof t === 'function' ? t('ui.confirmDeleteFingerprint', { host: host.host, port: host.port }) : `确定要删除主机 ${host.host}:${host.port} 的指纹记录吗?\n\n删除后下次连接将重新验证服务器指纹。`)) return; try { const result = await api.call('hosts.remove', { host: host.host, port: host.port }); @@ -12607,14 +12662,24 @@ async function testSshHostByIndex(index) { showToast(typeof t === 'function' ? t('toast.testingConnection', { host: host.id }) : `正在测试连接 ${host.id}...`, 'info'); try { - const execResult = await api.call('ssh.exec', { + const params = { host: host.host, port: host.port, user: host.username, // API 需要 'user' 而不是 'username' keyid: host.keyid || 'default', command: 'echo "TianshanOS SSH Test OK"', - trust_new: true - }); + trust_new: false + }; + let execResult = await api.call('ssh.exec', params); + if ([1001, 1002].includes(execResult.code)) { + const fingerprint = execResult.data?.fingerprint || execResult.data?.current_fingerprint; + if (fingerprint && confirm(runtimeText('confirmFingerprint') + '\n' + host.host + ':' + host.port + '\n' + fingerprint)) { + params.confirmed_fingerprint = fingerprint; + params.trust_new = execResult.code === 1002; + params.accept_changed = execResult.code === 1001; + execResult = await api.call('ssh.exec', params); + } + } if (execResult.code === 0) { showToast(typeof t === 'function' ? t('toast.connectionSuccess', { host: host.id }) : `连接 ${host.id} 成功!`, 'success'); @@ -12733,12 +12798,12 @@ async function doExportSshHost(hostId, recipientCert) { const result = await api.call('ssh.hosts.export', params); if (result.code !== 0) { - throw new Error(result.message || '导出失败'); + throw new Error(result.message || t('toast.exportFailed')); } const data = result.data; if (!data?.tscfg) { - throw new Error('无效的响应数据'); + throw new Error(t('toast.invalidResponse')); } // 下载文件 @@ -12752,7 +12817,7 @@ async function doExportSshHost(hostId, recipientCert) { document.body.removeChild(a); URL.revokeObjectURL(url); - showToast(typeof t === 'function' ? t('sshPage.hostConfigExported', { filename: data.filename }) : '已导出主机配置: ' + data.filename, 'success'); + showToast(typeof t === 'function' ? t('toast.hostConfigExported', { filename: data.filename }) : '已导出主机配置: ' + data.filename, 'success'); } /** @@ -12949,7 +13014,7 @@ async function removeHostByIndex(index) { return; } - if (!confirm(typeof t === 'function' ? t('ui.confirmRemoveHostLocal', { id: host.id }) : `确定要从列表中移除主机 "${host.id}" 吗?\n\n注意:这只会移除本地记录,不会删除已部署到服务器上的公钥。如需撤销公钥,请点击「撤销」按钮。`)) return; + if (!confirmAction(typeof t === 'function' ? t('ui.confirmRemoveHostLocal', { id: host.id }) : `确定要从列表中移除主机 "${host.id}" 吗?\n\n注意:这只会移除本地记录,不会删除已部署到服务器上的公钥。如需撤销公钥,请点击「撤销」按钮。`)) return; try { const result = await api.call('ssh.hosts.remove', { id: host.id }); @@ -13034,12 +13099,12 @@ async function doRevokeFromHost(index) { try { const result = await api.sshRevoke(host.host, host.username, password, host.keyid || 'default', host.port); - if (result.data?.revoked) { + if (result.data?.revoked === true) { resultBox.textContent = typeof t === 'function' ? t('securityPage.revokeSuccess', {count: result.data.removed_count || 1}) : `Revoked! Removed ${result.data.removed_count || 1} matching public key(s)`; resultBox.classList.add('success'); // 自动移除本地记录 - await api.call('ssh.hosts.remove', { id: host.id }); + requireApiSuccess(await api.call('ssh.hosts.remove', { id: host.id }), 'call'); showToast(typeof t === 'function' ? t('securityPage.revokedAndRemoved') : 'Revoked public key and removed host record', 'success'); setTimeout(() => { @@ -13053,7 +13118,7 @@ async function doRevokeFromHost(index) { // 提供移除本地记录的选项 revokeBtn.innerHTML = ' ' + (typeof t === 'function' ? t('securityPage.removeLocalRecord') : 'Remove Local Record Only'); revokeBtn.onclick = async () => { - await api.call('ssh.hosts.remove', { id: host.id }); + requireApiSuccess(await api.call('ssh.hosts.remove', { id: host.id }), 'call'); showToast(typeof t === 'function' ? t('securityPage.removedLocalRecord') : 'Removed local host record', 'success'); hideRevokeHostModal(); refreshSshHostsList(); @@ -13075,7 +13140,7 @@ async function doRevokeFromHost(index) { * 从安全页面删除 SSH 主机(保留兼容性) */ async function deleteSshHostFromSecurity(id) { - if (!confirm(typeof t === 'function' ? t('ui.confirmRemoveHostLocal2', { id }) : `确定要从列表中移除主机 "${id}" 吗?\n\n注意:这只会移除本地记录,不会删除已部署到服务器上的公钥。如需撤销公钥,请使用密钥管理中的「撤销」功能。`)) return; + if (!confirmAction(typeof t === 'function' ? t('ui.confirmRemoveHostLocal2', { id }) : `确定要从列表中移除主机 "${id}" 吗?\n\n注意:这只会移除本地记录,不会删除已部署到服务器上的公钥。如需撤销公钥,请使用密钥管理中的「撤销」功能。`)) return; try { const result = await api.call('ssh.hosts.remove', { id }); @@ -13091,9 +13156,9 @@ async function deleteSshHostFromSecurity(id) { } async function deleteKey(id) { - if (confirm(typeof t === 'function' ? t('ui.confirmDeleteKey', { id }) : `确定要删除密钥 "${id}" 吗?此操作不可撤销!`)) { + if (confirmAction(typeof t === 'function' ? t('ui.confirmDeleteKey', { id }) : `确定要删除密钥 "${id}" 吗?此操作不可撤销!`)) { try { - await api.keyDelete(id); + requireApiSuccess(await api.keyDelete(id), 'keyDelete'); showToast((typeof t === 'function' ? t('toast.keyDeleted') : '密钥已删除'), 'success'); await refreshSecurityPage(); } catch (e) { @@ -13118,7 +13183,7 @@ async function exportKey(id) { async function exportPrivateKey(id) { // 安全确认 - if (!confirm(typeof t === 'function' ? t('ui.confirmExportPrivateKey', { id }) : `安全警告\n\n您正在导出私钥 "${id}"。\n\n私钥是高度敏感的安全凭证,请确保:\n• 不要在公共网络传输\n• 不要分享给他人\n• 安全存储在本地\n\n确定要继续吗?`)) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmExportPrivateKey', { id }) : `安全警告\n\n您正在导出私钥 "${id}"。\n\n私钥是高度敏感的安全凭证,请确保:\n• 不要在公共网络传输\n• 不要分享给他人\n• 安全存储在本地\n\n确定要继续吗?`)) { return; } @@ -13159,7 +13224,7 @@ function showPubkeyModal(id, pubkey, type, comment) { @@ -13192,12 +13257,12 @@ function showPrivkeyModal(id, privkey, type, comment) {

${typeof t === 'function' ? t('securityPage.keyTypeLabel') : 'Type'}: ${escapeHtml(type)}${comment ? ' | ' + (typeof t === 'function' ? t('securityPage.commentLabel') : 'Comment') + ': ' + escapeHtml(comment) : ''}

- ${typeof t === 'function' ? t('securityPage.privkeyHint') : 'Save as ~/.ssh/' + escapeHtml(id) + ' and set permissions chmod 600'} + ${typeof t === 'function' ? t('securityPage.privkeyHint', {id}) : 'Save as ~/.ssh/' + escapeHtml(id) + ' and set permissions chmod 600'}

- +
`; @@ -13309,30 +13374,25 @@ async function deployKey() { const deployBtn = document.getElementById('deploy-btn'); resultBox.classList.remove('hidden', 'success', 'error'); - resultBox.textContent = typeof t === 'function' ? t('securityPage.deployingKey') : '正在部署密钥...'; + resultBox.textContent = typeof t === 'function' ? t('sshPage.deployingKey') : '正在部署密钥...'; deployBtn.disabled = true; try { // 调用 ssh.copyid API(与 CLI 逻辑一致) - const result = await api.sshCopyid(host, user, password, currentDeployKeyId, port, true); + const result = requireApiSuccess(await api.sshCopyid(host, user, password, currentDeployKeyId, port, true), 'ssh.copyid'); - if (result.data?.deployed) { - let msg = `部署成功!现在可以使用密钥 "${currentDeployKeyId}" 免密登录 ${user}@${host}`; - if (result.data.verified) { - msg += '\n公钥认证已验证'; - } else { - msg += '\n公钥认证验证跳过'; - } - resultBox.textContent = msg; - resultBox.classList.add('success'); - showToast((typeof t === 'function' ? t('toast.keyDeployed') : '密钥部署成功'), 'success'); + if (result.data?.deployed === true) { + const verified = result.data.verified === true; + resultBox.textContent = t(verified ? 'promptRepair.keyVerified' : 'promptRepair.keyUnverified', {id: currentDeployKeyId, target: `${user}@${host}`}); + resultBox.classList.add(verified ? 'success' : 'warning'); + showToast(resultBox.textContent, verified ? 'success' : 'warning', 6000); // 刷新已部署主机列表(后端 ssh.copyid 会自动注册主机) await loadSshHostsData(); } else { - throw new Error('部署失败'); + throw new Error(t('promptRepair.resultUnknown')); } } catch (e) { - resultBox.textContent = (typeof t === 'function' ? t('securityPage.deployFailedMsg', { msg: e.message }) : '部署失败: ' + e.message); + resultBox.textContent = (typeof t === 'function' ? t('pkiPage.deployFailedMsg', { msg: e.message }) : '部署失败: ' + e.message); resultBox.classList.add('error'); } finally { deployBtn.disabled = false; @@ -13384,9 +13444,9 @@ async function revokeKey() { try { // 调用 ssh.revoke API(与 CLI 逻辑一致) - const result = await api.sshRevoke(host, user, password, currentRevokeKeyId, port); + const result = requireApiSuccess(await api.sshRevoke(host, user, password, currentRevokeKeyId, port), 'ssh.revoke'); - if (result.data?.revoked) { + if (result.data?.revoked === true) { resultBox.textContent = typeof t === 'function' ? t('sshPage.revokeSuccess', { target: `${user}@${host}`, count: result.data.removed_count || 1 }) : `撤销成功!已从 ${user}@${host} 移除 ${result.data.removed_count || 1} 个匹配的公钥`; resultBox.classList.add('success'); showToast((typeof t === 'function' ? t('toast.keyRevoked') : '密钥撤销成功'), 'success'); @@ -13395,10 +13455,10 @@ async function revokeKey() { resultBox.classList.add('warning'); showToast((typeof t === 'function' ? t('toast.publicKeyNotFound') : '公钥未找到'), 'warning'); } else { - throw new Error('撤销失败'); + throw new Error(t('securityPage.revokeFailed')); } } catch (e) { - resultBox.textContent = (typeof t === 'function' ? t('securityPage.revokeFailedMsg', { msg: e.message }) : '撤销失败: ' + e.message); + resultBox.textContent = (typeof t === 'function' ? t('pkiPage.revokeFailedMsg', { msg: e.message }) : '撤销失败: ' + e.message); resultBox.classList.add('error'); } finally { revokeBtn.disabled = false; @@ -13412,8 +13472,8 @@ let currentMismatchInfo = null; function showHostMismatchModal(info) { currentMismatchInfo = info; document.getElementById('mismatch-host').value = `${info.host}:${info.port || 22}`; - document.getElementById('mismatch-stored-fp').value = info.stored_fingerprint || '未知'; - document.getElementById('mismatch-current-fp').value = info.current_fingerprint || '未知'; + document.getElementById('mismatch-stored-fp').value = info.stored_fingerprint || t('common.unknown'); + document.getElementById('mismatch-current-fp').value = info.current_fingerprint || t('common.unknown'); document.getElementById('host-mismatch-modal').classList.remove('hidden'); } @@ -13427,7 +13487,7 @@ async function removeAndRetry() { try { // 使用新的 hosts.update API 更新主机密钥 - await api.hostsUpdate(currentMismatchInfo.host, currentMismatchInfo.port || 22); + requireApiSuccess(await api.hostsUpdate(currentMismatchInfo.host, currentMismatchInfo.port || 22), 'hostsUpdate'); showToast((typeof t === 'function' ? t('toast.oldHostKeyRemoved') : '旧主机密钥已移除,请重新连接以信任新密钥'), 'success'); hideHostMismatchModal(); await refreshSecurityPage(); @@ -13437,9 +13497,9 @@ async function removeAndRetry() { } async function removeHost(host, port) { - if (confirm(typeof t === 'function' ? t('ui.confirmRemoveKnownHost', { host, port }) : `确定要移除主机 "${host}:${port}" 的记录吗?`)) { + if (confirmAction(typeof t === 'function' ? t('ui.confirmRemoveKnownHost', { host, port }) : `确定要移除主机 "${host}:${port}" 的记录吗?`)) { try { - await api.hostsRemove(host, port); + requireApiSuccess(await api.hostsRemove(host, port), 'hostsRemove'); showToast((typeof t === 'function' ? t('toast.hostRemoved') : '主机已移除'), 'success'); await refreshSecurityPage(); } catch (e) { @@ -13449,9 +13509,9 @@ async function removeHost(host, port) { } async function clearAllHosts() { - if (confirm(typeof t === 'function' ? t('automation.confirmClearKnownHosts') : '确定要清除所有已知主机记录吗?此操作不可撤销!')) { + if (confirmAction(typeof t === 'function' ? t('ui.confirmClearKnownHosts') : '确定要清除所有已知主机记录吗?此操作不可撤销!')) { try { - await api.hostsClear(); + requireApiSuccess(await api.hostsClear(), 'hostsClear'); showToast((typeof t === 'function' ? t('toast.allHostsCleared') : '已清除所有已知主机'), 'success'); await refreshSecurityPage(); } catch (e) { @@ -13468,6 +13528,7 @@ async function clearAllHosts() { * 刷新配置包状态卡片 */ async function refreshConfigPackStatus() { + const pageCurrent = capturePageValidity(); const statusIcon = document.getElementById('pack-status-icon'); const statusText = document.getElementById('pack-status-text'); const deviceTypeBadge = document.getElementById('pack-device-type-badge'); @@ -13478,9 +13539,10 @@ async function refreshConfigPackStatus() { try { const result = await api.configPackInfo(); + if (!pageCurrent()) return; const data = result.data; - if (!data) throw new Error('无响应数据'); + if (!data) throw new Error(t('promptRepair.noResponse')); // 存储状态供弹窗使用 window._configPackStatus = data; @@ -13513,6 +13575,7 @@ async function refreshConfigPackStatus() { } } catch (e) { + if (!pageCurrent()) return; console.error('Refresh config pack status error:', e); statusIcon.innerHTML = ''; statusText.textContent = (typeof t === 'function' ? t('common.loadFailed') : '加载失败'); @@ -13550,7 +13613,7 @@ async function loadConfigPackCert() { loading.style.display = 'none'; content.classList.remove('hidden'); } catch (e) { - loading.textContent = typeof t === 'function' ? t('securityPage.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message; + loading.textContent = typeof t === 'function' ? t('pkiPage.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message; } } @@ -13598,13 +13661,13 @@ async function verifyConfigPack() { if (!content) { resultBox.className = 'result-box error'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.uploadOrPasteContent') : '请上传文件或粘贴配置包内容'; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.uploadOrPasteContent') : '请上传文件或粘贴配置包内容'; resultBox.classList.remove('hidden'); return; } resultBox.className = 'result-box'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.verifying') : '验证中...'; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.verifying') : '验证中...'; resultBox.classList.remove('hidden'); preview.classList.add('hidden'); @@ -13622,21 +13685,21 @@ async function verifyConfigPack() { const sig = data.signature; document.getElementById('pack-preview-content').innerHTML = `
-
签名者:${sig.signer_cn || '-'}
-
组织:${sig.signer_ou || '-'}
-
官方签名:${sig.is_official ? '是' : '否'}
-
签名时间:${sig.signed_at ? formatTimestamp(sig.signed_at) : '-'}
+
${t('ssh.signer')}: ${sig.signer_cn || '-'}
+
${t('promptRepair.organization')}: ${sig.signer_ou || '-'}
+
${t('securityPage.officialSignature')}: ${sig.is_official ? t('common.yes') : t('common.no')}
+
${t('securityPage.signedAt')}: ${sig.signed_at ? formatTimestamp(sig.signed_at) : '-'}
`; preview.classList.remove('hidden'); } } else { resultBox.className = 'result-box error'; - resultBox.textContent = (typeof t === 'function' ? t('securityPage.verifyFailed') : '验证失败') + ': ' + (data.result_message || (typeof t === 'function' ? t('securityPage.signatureInvalid') : '签名无效')); + resultBox.textContent = (typeof t === 'function' ? t('pkiPage.verifyFailed') : '验证失败') + ': ' + (data.result_message || (typeof t === 'function' ? t('pkiPage.signatureInvalid') : '签名无效')); } } catch (e) { resultBox.className = 'result-box error'; - resultBox.textContent = (typeof t === 'function' ? t('securityPage.verifyFailed') : '验证失败') + ': ' + e.message; + resultBox.textContent = (typeof t === 'function' ? t('pkiPage.verifyFailed') : '验证失败') + ': ' + e.message; } } @@ -13647,13 +13710,13 @@ async function importConfigPack() { if (!content) { resultBox.className = 'result-box error'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.uploadOrPasteContent') : '请上传文件或粘贴配置包内容'; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.uploadOrPasteContent') : '请上传文件或粘贴配置包内容'; resultBox.classList.remove('hidden'); return; } resultBox.className = 'result-box'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.importing') : '导入中...'; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.importing') : '导入中...'; resultBox.classList.remove('hidden'); try { @@ -13695,9 +13758,12 @@ async function importConfigPack() { * 显示配置包应用确认对话框 * 当通过文件管理上传 .tscfg 文件并验证成功后调用 */ -function showConfigPackApplyConfirm(path, packInfo) { +function showConfigPackApplyConfirm(path, packInfo, verificationCurrent = () => true) { + if (packInfo?.valid !== true) { showToast(t('promptRepair.packInvalid'), 'error'); return; } + if (!i18n.complete('securityPage.configPackSavedApplyNow')) return; + closeConfigPackApplyConfirm(); const sig = packInfo.signature || {}; - const signerInfo = sig.signer_cn ? `${sig.signer_cn}${sig.is_official ? ' (官方)' : ''}` : '未知'; + const signerInfo = sig.signer_cn ? `${sig.signer_cn}${sig.is_official ? t('promptRepair.officialSuffix') : ''}` : t('common.unknown'); // 创建确认对话框 const dialog = document.createElement('div'); @@ -13712,8 +13778,8 @@ function showConfigPackApplyConfirm(path, packInfo) {
${typeof t === 'function' ? t('securityPage.verifySuccess') : 'Verification Successful'}
-
${typeof t === 'function' ? t('securityPage.fileName') : 'File'}: ${path.split('/').pop()}
-
${typeof t === 'function' ? t('securityPage.signer') : 'Signer'}: ${signerInfo}
+
${typeof t === 'function' ? t('securityPage.fileName') : 'File'}: ${escapeHtml(path.split('/').pop())}
+
${typeof t === 'function' ? t('securityPage.signer') : 'Signer'}: ${escapeHtml(signerInfo)}
${sig.is_official ? '
' + (typeof t === 'function' ? t('securityPage.officialSignature') : 'Official Signature') + '
' : ''}
@@ -13723,12 +13789,14 @@ function showConfigPackApplyConfirm(path, packInfo) { `; document.body.appendChild(dialog); + dialog.verificationCurrent = verificationCurrent; + document.getElementById('config-pack-apply-button').onclick = () => applyConfigPackFromPath(path); } function closeConfigPackApplyConfirm() { @@ -13741,27 +13809,45 @@ function closeConfigPackApplyConfirm() { /** * 应用指定路径的配置包 */ +let configPackAttempt = 0; async function applyConfigPackFromPath(path) { - closeConfigPackApplyConfirm(); - showToast(typeof t === 'function' ? t('toast.applyingConfig') : '正在应用配置...', 'info'); - + const dialog = document.getElementById('config-pack-apply-confirm'); + const button = document.getElementById('config-pack-apply-button'); + if (button?.disabled || !i18n.complete('securityPage.configPackSavedApplyNow')) return; + if (dialog?.verificationCurrent && !dialog.verificationCurrent()) { + showToast(t('promptRepair.packRevalidate'), 'warning'); return; + } + const attempt = ++configPackAttempt; + const current = () => attempt === configPackAttempt && document.getElementById('config-pack-apply-confirm') === dialog; + if (button) button.disabled = true; + // Keep a per-task result outside the modal, including after the modal is closed. + let results = document.getElementById('config-pack-task-results'); + if (!results) { + results = document.createElement('div'); results.id = 'config-pack-task-results'; + results.setAttribute('role', 'status'); + const heading = document.createElement('h3'); heading.textContent = t('promptRepair.taskResults'); + results.appendChild(heading); document.querySelector('main').appendChild(results); + } + const row = document.createElement('div'); results.appendChild(row); + const record = message => { row.textContent = t('promptRepair.taskAttempt', {path, attempt}) + ' — ' + message; }; + record(t('toast.applyingConfig')); + showToast(path + ': ' + t('toast.applyingConfig'), 'info', 3000, {isCurrent: current}); try { - const result = await api.call('config.pack.apply', { path }, 'POST'); - if (result.code !== 0) { - throw new Error(result.message || result.data?.result_message || '应用失败'); - } - + const result = requireApiSuccess(await api.call('config.pack.apply', { path }, 'POST'), 'config.pack.apply'); const data = result.data; - if (data.success) { - const modules = data.applied_modules || []; - const moduleList = modules.length > 0 ? modules.join(', ') : '无'; - showToast(typeof t === 'function' ? t('toast.configApplied', { modules: moduleList }) : `配置已应用\n模块: ${moduleList}`, 'success', 5000); - } else { - showToast(typeof t === 'function' ? t('toast.applyFailedMsg', { msg: data.result_message }) : `应用失败: ${data.result_message}`, 'error'); + if (data?.success !== true) throw new ApiOperationError({message: data?.result_message}, 'config.pack.apply'); + const message = t('promptRepair.packApplied') + (data.applied_modules?.length ? '\n' + t('promptRepair.details', {detail: data.applied_modules.join(', ')}) : ''); + record(message); + if (current()) { + showToast(path + ': ' + message, 'success', 5000, {isCurrent: current}); + dialog?.remove(); } } catch (e) { - console.error('Apply config pack error:', e); - showToast(typeof t === 'function' ? t('toast.applyFailedMsg', { msg: e.message }) : '应用失败: ' + e.message, 'error'); + const message = e.uncertain ? e.message : t('toast.applyFailedMsg', {msg: e.message}); + record(message); + if (current()) showToast(path + ': ' + message, 'error', 8000, {isCurrent: current}); + } finally { + if (current() && button) button.disabled = false; } } @@ -13834,7 +13920,7 @@ async function packExportBrowseRefresh() { packExportCurrentEntries = filteredEntries; if (filteredEntries.length === 0) { - fileList.innerHTML = '
没有配置文件 (.json)
'; + fileList.innerHTML = ("
" + t('pkiPage.noConfigFiles') + "
"); return; } @@ -13874,7 +13960,7 @@ async function packExportBrowseRefresh() { packExportUpdateSelectedDisplay(); } catch (e) { - fileList.innerHTML = `
加载失败: ${e.message}
`; + fileList.innerHTML = `
${t('common.loadFailed')}: ${escapeHtml(e.message)}
`; } } @@ -13919,7 +14005,7 @@ async function packExportToggleFile(fileName, checked) { if (result.code !== 0) throw new Error(result.message); const rawContent = result.data?.content; - if (rawContent === undefined || rawContent === null) throw new Error('文件内容为空'); + if (rawContent === undefined || rawContent === null) throw new Error(t('toast.fileContentEmpty')); // 后端 storage.read 会自动解析 JSON let contentStr; @@ -13959,13 +14045,13 @@ function packExportUpdateSelectedDisplay() { selectedDiv.style.display = 'block'; - let text = `已选择 ${files.length} 个文件`; + let text = t('promptRepair.filesSelected', {count: files.length}); if (loadingFiles.length > 0) { - text += ` (${loadingFiles.length} ${t('security.filesLoading')})`; + text += ` (${loadingFiles.length} ${t('securityPage.filesLoading')})`; selectedDiv.style.background = 'rgba(245, 158, 11, 0.06)'; generateBtn.disabled = true; } else if (errorFiles.length > 0) { - text += ` (${errorFiles.length} 个错误: ${errorFiles[0][1].error})`; + text += '\n' + t('promptRepair.fileErrors', {count: errorFiles.length, message: errorFiles[0][1].error}); selectedDiv.style.background = 'rgba(244, 63, 94, 0.06)'; generateBtn.disabled = errorFiles.length === files.length; // 全部错误则禁用 } else { @@ -14037,7 +14123,7 @@ async function exportConfigPack() { if (!name) { resultBox.className = 'result-box error'; resultBox.style.visibility = 'visible'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.enterConfigName') : '请输入配置名称'; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.enterConfigName') : '请输入配置名称'; return; } @@ -14046,7 +14132,7 @@ async function exportConfigPack() { if (okFiles.length === 0) { resultBox.className = 'result-box error'; resultBox.style.visibility = 'visible'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.selectConfigFile') : '请选择配置文件'; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.selectConfigFile') : '请选择配置文件'; return; } @@ -14074,13 +14160,13 @@ async function exportConfigPack() { } catch (e) { resultBox.className = 'result-box error'; resultBox.style.visibility = 'visible'; - resultBox.textContent = (typeof t === 'function' ? t('securityPage.invalidJsonConfigMsg', { msg: e.message }) : '配置文件不是有效的 JSON: ' + e.message); + resultBox.textContent = (typeof t === 'function' ? t('pkiPage.invalidJsonConfigMsg', { msg: e.message }) : '配置文件不是有效的 JSON: ' + e.message); return; } resultBox.className = 'result-box'; resultBox.style.visibility = 'visible'; - resultBox.textContent = typeof t === 'function' ? t('securityPage.generatingPackWithCount', { count: okFiles.length }) : `生成配置包中 (${okFiles.length} 个文件)...`; + resultBox.textContent = typeof t === 'function' ? t('pkiPage.generatingPackWithCount', { count: okFiles.length }) : `生成配置包中 (${okFiles.length} 个文件)...`; document.getElementById('pack-export-tscfg').value = ''; try { @@ -14097,12 +14183,10 @@ async function exportConfigPack() { const savedPath = data.saved_path || ''; resultBox.className = 'result-box success'; - let resultHtml = `配置包已生成
文件名: ${fileName}
大小: ${fileSize} 字节 (${okFiles.length} 个配置文件)`; - if (savedPath) { - resultHtml += `
已保存到: ${savedPath}`; - } - resultBox.innerHTML = resultHtml; - + resultBox.style.whiteSpace = 'pre-wrap'; + resultBox.textContent = t('promptRepair.packGenerated', {name: fileName, size: fileSize, count: okFiles.length}); + if (savedPath) resultBox.textContent += '\n' + t('securityPage.savedTo') + ': ' + savedPath; + // 显示输出 const tscfgTextarea = document.getElementById('pack-export-tscfg'); tscfgTextarea.value = tscfgContent; @@ -14117,7 +14201,7 @@ async function exportConfigPack() { // 显示保存路径 const savedPathSpan = document.getElementById('pack-export-saved-path'); if (savedPath && savedPathSpan) { - savedPathSpan.textContent = typeof t === 'function' ? t('securityPage.savedToDevice') : '已保存到设备'; + savedPathSpan.textContent = typeof t === 'function' ? t('pkiPage.savedToDevice') : '已保存到设备'; savedPathSpan.style.display = 'inline'; } @@ -14126,13 +14210,13 @@ async function exportConfigPack() { if (!tscfgContent) { console.warn('[ConfigPack] tscfg content is empty!'); - resultBox.innerHTML += '
警告: 配置包内容为空'; + resultBox.textContent += '\n' + t('pkiPage.contentEmpty'); } } catch (e) { console.error('[ConfigPack] Export error:', e); resultBox.className = 'result-box error'; - resultBox.textContent = (typeof t === 'function' ? t('securityPage.generationFailedMsg', { msg: e.message }) : '生成失败: ' + e.message); + resultBox.textContent = (typeof t === 'function' ? t('pkiPage.generationFailedMsg', { msg: e.message }) : '生成失败: ' + e.message); } } @@ -14159,7 +14243,7 @@ function downloadPackTscfg() { document.body.removeChild(a); URL.revokeObjectURL(url); - showToast(typeof t === 'function' ? t('toast.configPackDownloaded', { filename }) : '配置包已下载: ' + filename, 'success'); + showToast(t('promptRepair.downloadStarted'), 'info'); } // 配置包:列表弹窗 @@ -14173,6 +14257,7 @@ function hideConfigPackListModal() { } async function refreshConfigPackList() { + const pageCurrent = capturePageValidity(); const path = document.getElementById('pack-list-path').value.trim() || '/sdcard/config'; const loading = document.getElementById('pack-list-loading'); const table = document.getElementById('pack-list-table'); @@ -14183,6 +14268,7 @@ async function refreshConfigPackList() { try { const result = await api.configPackList(path); + if (!pageCurrent()) return; if (result.code !== 0) throw new Error(result.message || result.error); const data = result.data; @@ -14219,13 +14305,14 @@ async function refreshConfigPackList() { table.classList.remove('hidden'); } catch (e) { + if (!pageCurrent()) return; loading.textContent = (typeof t === 'function' ? t('securityPage.packListLoadFailed') : '加载失败') + ': ' + e.message; } } async function importPackFromList(filePath) { const msg = typeof t === 'function' ? t('securityPage.confirmImportPack', { path: filePath }) : '确定要导入配置包: ' + filePath + ' ?'; - if (!confirm(msg)) return; + if (!confirmAction(msg)) return; try { const result = await api.configPackImport(null, filePath, false); @@ -14254,135 +14341,112 @@ function formatBytes(bytes) { /** * 刷新证书状态卡片 */ +// Certificate UI helpers intentionally leave the global API protocol unchanged. +function certText(key, fallback, params = {}) { + const value = typeof t === 'function' ? t(key, params) : key; + return typeof value === 'string' && value !== key ? value : fallback; +} +function certError(result, fallback) { + for (const value of [result?.message, result?.error]) { + if (typeof value === 'string' && value.trim()) return value; + } + return fallback; +} +function certValidity(value) { + const labels = {none: 'No certificate', invalid: 'Certificate cannot be parsed', + time_unverified: 'Awaiting device time', not_yet_valid: 'Not yet valid', + valid: 'Within validity period', expired: 'Expired'}; + return certText('pkiRepair.' + (labels[value] ? value : 'unknown'), labels[value] || 'Unknown / unconfirmed'); +} +function certExpiry(info) { + const seconds = info?.seconds_until_expiry; + if (!['valid', 'expired'].includes(info?.validity) || typeof seconds !== 'number') return ''; + if (seconds >= 0 && seconds < 86400) return certText('pkiRepair.lessDay', 'Expires in less than a day'); + if (seconds < 0 && seconds > -86400) return certText('pkiRepair.expiredLessDay', 'Expired less than a day ago'); + const days = Math.floor(Math.abs(seconds) / 86400); + return seconds < 0 ? certText('pkiPage.expiredDays', `Expired ${days} days ago`, {days}) : + certText('pkiPage.remainingDays', `${days} days remaining`, {days}); +} async function refreshCertStatus() { - const statusIcon = document.getElementById('cert-status-icon'); - const statusText = document.getElementById('cert-status-text'); - const expiryBadge = document.getElementById('cert-expiry-badge'); - const infoDetails = document.getElementById('cert-info-details'); - const noKeyHint = document.getElementById('cert-no-key-hint'); - - // 按钮引用 - const btnGenKey = document.getElementById('btn-cert-gen-key'); - const btnGenCSR = document.getElementById('btn-cert-gen-csr'); - const btnInstall = document.getElementById('btn-cert-install'); - const btnInstallCA = document.getElementById('btn-cert-install-ca'); - const btnView = document.getElementById('btn-cert-view'); - const btnDelete = document.getElementById('btn-cert-delete'); - - if (!statusIcon) return; // 不在安全页面 - + const pageCurrent = capturePageValidity(); + if (!document.getElementById('cert-status-icon')) return; try { const result = await api.certStatus(); + if (!pageCurrent()) return; + if (result.code !== 0 || !result.data) throw new Error(certError(result, 'Status unavailable')); const data = result.data; - - if (!data) throw new Error('无响应数据'); - - // 存储状态供弹窗使用 window._certPkiStatus = data; - - // 根据状态更新 UI - const hasKey = data.has_private_key; - const hasCert = data.has_certificate; - const hasCa = data.has_ca_chain; - - // 更新按钮状态 - btnGenKey.disabled = false; - btnGenCSR.disabled = !hasKey; - btnInstall.disabled = !hasKey; - btnInstallCA.disabled = !hasKey; - btnView.disabled = !hasCert; - btnDelete.disabled = !hasKey && !hasCert && !hasCa; - - // 状态显示 - switch (data.status) { - case 'not_initialized': - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('securityPage.notInitialized') : 'Not Initialized'; - noKeyHint.style.display = 'block'; - infoDetails.style.display = 'none'; - expiryBadge.style.display = 'none'; - break; - case 'key_generated': - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('securityPage.keyGeneratedAwaitCsr') : 'Key Generated, Awaiting CSR'; - noKeyHint.style.display = 'none'; - infoDetails.style.display = 'none'; - expiryBadge.style.display = 'none'; - break; - case 'csr_pending': - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('securityPage.csrPendingSign') : 'CSR Generated, Awaiting Signing'; - noKeyHint.style.display = 'none'; - infoDetails.style.display = 'none'; - expiryBadge.style.display = 'none'; - break; - case 'activated': - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('securityPage.activated') : 'Activated'; - noKeyHint.style.display = 'none'; - infoDetails.style.display = 'block'; - updateCertInfoDetails(data.cert_info); - break; - case 'expired': - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('securityPage.expired') : 'Expired'; - noKeyHint.style.display = 'none'; - infoDetails.style.display = 'block'; - updateCertInfoDetails(data.cert_info); - break; - case 'error': - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('common.error') : 'Error'; - noKeyHint.style.display = 'none'; - infoDetails.style.display = 'none'; - expiryBadge.style.display = 'none'; - break; - default: - statusIcon.innerHTML = ''; - statusText.textContent = data.status_display || data.status; + for (const [id, disabled] of Object.entries({ + 'btn-cert-gen-key': false, 'btn-cert-gen-csr': !data.has_private_key, + 'btn-cert-install': !data.has_private_key, 'btn-cert-install-ca': false, + 'btn-cert-view': !data.has_certificate, + 'btn-cert-delete': !data.has_private_key && !data.has_certificate && !data.has_ca_chain + })) document.getElementById(id).disabled = disabled; + document.getElementById('cert-status-icon').textContent = ''; + document.getElementById('cert-status-text').textContent = certValidity(data.validity); + const stored = certText('pkiRepair.stored', 'Saved'); + const missing = certText('pkiRepair.missing', 'Missing'); + document.getElementById('cert-material-state').textContent = + `${certText('pkiRepair.key', 'Key')}: ${data.has_private_key ? stored : missing} · ` + + `${certText('pkiRepair.certificate', 'Certificate')}: ${data.has_certificate ? stored : missing} · ` + + `${certText('pkiRepair.clientCa', 'Client verification CA')}: ${data.has_ca_chain ? stored : missing}`; + const https = data.https; + document.getElementById('cert-https-state').textContent = 'HTTPS: ' + + (typeof https?.running !== 'boolean' ? certValidity() : + certText(https.running ? 'pkiRepair.running' : 'pkiRepair.stopped', https.running ? 'Running' : 'Not running')) + + (https?.port ? ` (${https.port})` : '') + + (https?.last_error ? ` — ${https.last_error_stage}: ${https.last_error}` : ''); + document.getElementById('cert-blocked-state').textContent = (data.blocked_by || []).map( + reason => certText('pkiRepair.block_' + reason, reason)).join(' · '); + document.getElementById('cert-restart-state').textContent = data.restart_required ? + certText('pkiRepair.restart', 'Stored materials changed. The running service still uses the previous materials. Restart the device to apply; startup conditions must be met.') : ''; + document.getElementById('cert-active-fingerprint').textContent = https?.loaded_certificate_sha256 ? + `${certText('pkiRepair.activeFingerprint', 'Active certificate SHA-256')}: ${https.loaded_certificate_sha256}` : ''; + document.getElementById('cert-no-key-hint').style.display = data.has_private_key ? 'none' : 'block'; + document.getElementById('cert-info-details').style.display = data.has_certificate ? 'block' : 'none'; + updateCertInfoDetails(data.cert_info); + // Read the device clock, never display the browser's clock as device evidence. + try { + const time = await api.timeInfo(); + if (!pageCurrent()) return; + if (time.code !== 0 || !time.data) throw new Error('Time unavailable'); + document.getElementById('cert-device-time').textContent = + `${certText('pkiRepair.deviceTime', 'Device time')}: ${time.data.datetime || '—'} · ${time.data.source || '—'} · ` + + certText(time.data.synced ? 'pkiRepair.synced' : 'pkiRepair.unsynced', time.data.synced ? 'Synchronized' : 'Not synchronized'); + } catch (_) { + if (!pageCurrent()) return; + document.getElementById('cert-device-time').textContent = certText('pkiRepair.timeUnknown', 'Device time unavailable; retry refresh'); } - } catch (e) { - console.error('Refresh cert status error:', e); - statusIcon.innerHTML = ''; - statusText.textContent = typeof t === 'function' ? t('common.loadFailed') : 'Load Failed'; - if (noKeyHint) noKeyHint.style.display = 'none'; - if (infoDetails) infoDetails.style.display = 'none'; - if (expiryBadge) expiryBadge.style.display = 'none'; - } -} - -function updateCertInfoDetails(certInfo) { - if (!certInfo) return; - - document.getElementById('cert-subject-cn').textContent = certInfo.subject_cn || '-'; - document.getElementById('cert-issuer-cn').textContent = certInfo.issuer_cn || '-'; - document.getElementById('cert-not-before').textContent = certInfo.not_before ? formatTimestamp(certInfo.not_before) : '-'; - document.getElementById('cert-not-after').textContent = certInfo.not_after ? formatTimestamp(certInfo.not_after) : '-'; - document.getElementById('cert-serial').textContent = certInfo.serial || '-'; - document.getElementById('cert-valid-status').textContent = certInfo.is_valid ? (typeof t === 'function' ? t('securityPage.valid') : 'Valid') : (typeof t === 'function' ? t('securityPage.invalid') : 'Invalid'); - - // 更新过期徽章 - const expiryBadge = document.getElementById('cert-expiry-badge'); - if (certInfo.days_until_expiry !== undefined) { - expiryBadge.style.display = 'inline-block'; - if (certInfo.days_until_expiry < 0) { - expiryBadge.textContent = (typeof t === 'function' ? t('securityPage.expiredDays', {days: Math.abs(certInfo.days_until_expiry)}) : `已过期 ${Math.abs(certInfo.days_until_expiry)} 天`); - expiryBadge.className = 'badge badge-danger'; - } else if (certInfo.days_until_expiry < 30) { - expiryBadge.textContent = (typeof t === 'function' ? t('securityPage.expiringDays', {days: certInfo.days_until_expiry}) : `${certInfo.days_until_expiry} 天后过期`); - expiryBadge.className = 'badge badge-warning'; - } else { - expiryBadge.textContent = (typeof t === 'function' ? t('securityPage.remainingDays', {days: certInfo.days_until_expiry}) : `剩余 ${certInfo.days_until_expiry} 天`); - expiryBadge.className = 'badge badge-service-style'; - } - } else { - expiryBadge.style.display = 'none'; - } + if (!pageCurrent()) return; + document.getElementById('cert-status-text').textContent = certText('pkiPage.statusLoadFailed', 'Status refresh failed'); + } +} +function updateCertInfoDetails(info) { + const badge = document.getElementById('cert-expiry-badge'); + badge.textContent = certExpiry(info); + badge.style.display = badge.textContent ? 'inline-block' : 'none'; + if (!info) return; + for (const [id, value] of Object.entries({ + 'cert-subject-cn': info.subject_cn, 'cert-issuer-cn': info.issuer_cn, + 'cert-not-before': info.validity !== 'invalid' && info.not_before ? formatTimestamp(info.not_before) : '-', + 'cert-not-after': info.validity !== 'invalid' && info.not_after ? formatTimestamp(info.not_after) : '-', + 'cert-serial': (info.serial || '-') + (info.serial_truncated ? '…' : ''), + 'cert-valid-status': certValidity(info.validity) + })) document.getElementById(id).textContent = value || '-'; +} +async function syncCertificateTime() { + const button = document.getElementById('cert-time-sync'); + button.disabled = true; + try { + const result = await api.timeSync(Date.now()); + if (result.code !== 0) throw new Error(certError(result, 'Time update failed')); + await refreshCertStatus(); + } catch (e) { + document.getElementById('cert-device-time').textContent = certError(e, 'Time update failed'); + } finally { button.disabled = false; } } -// ====== 证书管理弹窗 ====== - function showCertGenKeyModal() { const modal = document.getElementById('cert-genkey-modal'); const warningBox = document.getElementById('cert-genkey-existing-warning'); @@ -14410,25 +14474,25 @@ async function generateCertKeypair() { const force = window._certPkiStatus?.has_private_key; resultBox.classList.remove('hidden', 'success', 'error'); - resultBox.textContent = typeof t === 'function' ? t('securityPage.generatingKeyPair') : '正在生成密钥对...'; + resultBox.textContent = certText('pkiPage.generatingKeyPair', '正在生成密钥对...'); btn.disabled = true; try { const result = await api.certGenerateKeypair(force); - if (result.code === 0 || result.data?.success) { - resultBox.textContent = typeof t === 'function' ? t('securityPage.ecdsaKeyPairSuccess') : 'ECDSA P-256 密钥对生成成功!'; + if (result.code === 0) { + resultBox.textContent = certText('pkiPage.ecdsaKeyPairSuccess', 'ECDSA P-256 密钥对生成成功!'); resultBox.classList.add('success'); - showToast(typeof t === 'function' ? t('toast.keypairGenerated') : '密钥对生成成功', 'success'); + showToast(certText('toast.keypairGenerated', '密钥对生成成功'), 'success'); setTimeout(() => { hideCertGenKeyModal(); refreshCertStatus(); }, 1000); } else { - throw new Error(result.message || '生成失败'); + throw new Error(certError(result, t('toast.generateFailed'))); } } catch (e) { - resultBox.textContent = (typeof t === 'function' ? t('securityPage.generationFailedMsg', { msg: e.message }) : '生成失败: ' + e.message); + resultBox.textContent = (certText('pkiPage.generationFailedMsg', '生成失败: ' + e.message, { msg: e.message })); resultBox.classList.add('error'); } finally { btn.disabled = false; @@ -14457,7 +14521,7 @@ async function generateCSR() { const btn = document.getElementById('csr-gen-btn'); resultBox.classList.remove('hidden', 'success', 'error'); - resultBox.textContent = typeof t === 'function' ? t('securityPage.generatingCsr') : '正在生成 CSR...'; + resultBox.textContent = certText('pkiPage.generatingCsr', '正在生成 CSR...'); btn.disabled = true; try { @@ -14471,12 +14535,12 @@ async function generateCSR() { resultBox.classList.add('hidden'); csrResultBox.classList.remove('hidden'); document.getElementById('csr-pem-output').value = result.data.csr_pem; - showToast(typeof t === 'function' ? t('toast.csrGenerated') : 'CSR 生成成功', 'success'); + showToast(certText('toast.csrGenerated', 'CSR 生成成功'), 'success'); } else { - throw new Error(result.message || '生成失败'); + throw new Error(certError(result, t('toast.generateFailed'))); } } catch (e) { - resultBox.textContent = (typeof t === 'function' ? t('securityPage.generationFailedMsg', { msg: e.message }) : '生成失败: ' + e.message); + resultBox.textContent = (certText('pkiPage.generationFailedMsg', '生成失败: ' + e.message, { msg: e.message })); resultBox.classList.add('error'); } finally { btn.disabled = false; @@ -14486,9 +14550,9 @@ async function generateCSR() { function copyCSRToClipboard() { const csr = document.getElementById('csr-pem-output').value; navigator.clipboard.writeText(csr).then(() => { - showToast(typeof t === 'function' ? t('toast.csrCopied') : 'CSR 已复制到剪贴板', 'success'); + showToast(certText('toast.csrCopied', 'CSR 已复制到剪贴板'), 'success'); }).catch(e => { - showToast(typeof t === 'function' ? t('toast.copyFailedMsg', { msg: e.message }) : '复制失败: ' + e.message, 'error'); + showToast(certText('toast.copyFailedMsg', '复制失败: ' + e.message, { msg: e.message }), 'error'); }); } @@ -14503,34 +14567,40 @@ function hideCertInstallModal() { document.getElementById('cert-install-modal').classList.add('hidden'); } -async function installCertificate() { - const certPem = document.getElementById('cert-pem-input').value.trim(); - if (!certPem) { - showToast(typeof t === 'function' ? t('toast.enterCertPem') : '请输入证书 PEM', 'error'); - return; - } - - const resultBox = document.getElementById('cert-install-result'); +async function installCertificate() { await installCertMaterial(false); } +async function installCertMaterial(ca) { + const pem = document.getElementById(ca ? 'ca-pem-input' : 'cert-pem-input').value.trim(); + const resultBox = document.getElementById(ca ? 'ca-install-result' : 'cert-install-result'); + const button = document.getElementById(ca ? 'cert-ca-submit' : 'cert-install-submit'); + if (button.disabled) return; resultBox.classList.remove('hidden', 'success', 'error'); - resultBox.textContent = typeof t === 'function' ? t('securityPage.installingCert') : '正在安装证书...'; - + if (!pem) { + resultBox.textContent = certText('pkiRepair.empty', 'Provide PEM text'); + resultBox.classList.add('error'); return; + } + button.disabled = true; + resultBox.textContent = certText('pkiPage.installingCert', 'Saving certificate materials…'); + let saved = false; try { - const result = await api.certInstall(certPem); - if (result.code === 0 || result.data?.success) { - resultBox.textContent = typeof t === 'function' ? t('securityPage.certInstalledSuccess') : '证书安装成功!'; + const result = ca ? await api.certInstallCA(pem) : await api.certInstall(pem); + saved = result.code === 0; + if (saved) { + resultBox.textContent = certText('pkiRepair.saved', 'Saved. Check validity and HTTPS status below.'); resultBox.classList.add('success'); - showToast(typeof t === 'function' ? t('toast.certInstalled') : '证书安装成功', 'success'); - - setTimeout(() => { - hideCertInstallModal(); - refreshCertStatus(); - }, 1000); } else { - throw new Error(result.message || '安装失败'); + const msg = certError(result, certText('pkiPage.installFailed', 'Installation failed')); + resultBox.textContent = certText('pkiPage.installFailedMsg', `Installation failed: ${msg}`, {msg}); + resultBox.classList.add('error'); } - } catch (e) { - resultBox.textContent = (typeof t === 'function' ? t('securityPage.installFailedMsg', { msg: e.message }) : '安装失败: ' + e.message); + } catch (_) { + // A lost response is not proof that the server did not persist the request. + resultBox.textContent = certText('pkiRepair.unconfirmed', 'Installation result unconfirmed. Refresh status to check before retrying.'); resultBox.classList.add('error'); + } finally { button.disabled = false; } + if (saved) { + try { await refreshCertStatus(); } catch (_) { /* Saved result remains authoritative. */ } + // Observe the asynchronous coordinator without reposting or starting HTTPS from UI. + setTimeout(() => refreshCertStatus().catch(() => {}), 5500); } } @@ -14545,36 +14615,7 @@ function hideCertInstallCAModal() { document.getElementById('cert-ca-modal').classList.add('hidden'); } -async function installCAChain() { - const caPem = document.getElementById('ca-pem-input').value.trim(); - if (!caPem) { - showToast(typeof t === 'function' ? t('toast.enterCaPem') : '请输入 CA 证书链 PEM', 'error'); - return; - } - - const resultBox = document.getElementById('ca-install-result'); - resultBox.classList.remove('hidden', 'success', 'error'); - resultBox.textContent = typeof t === 'function' ? t('securityPage.installingCaCert') : '正在安装 CA 证书链...'; - - try { - const result = await api.certInstallCA(caPem); - if (result.code === 0 || result.data?.success) { - resultBox.textContent = typeof t === 'function' ? t('securityPage.caCertInstalledSuccess') : 'CA 证书链安装成功!'; - resultBox.classList.add('success'); - showToast(typeof t === 'function' ? t('toast.caInstalled') : 'CA 证书链安装成功', 'success'); - - setTimeout(() => { - hideCertInstallCAModal(); - refreshCertStatus(); - }, 1000); - } else { - throw new Error(result.message || '安装失败'); - } - } catch (e) { - resultBox.textContent = (typeof t === 'function' ? t('securityPage.installFailedMsg', { msg: e.message }) : '安装失败: ' + e.message); - resultBox.classList.add('error'); - } -} +async function installCAChain() { await installCertMaterial(true); } async function showCertViewModal() { const modal = document.getElementById('cert-view-modal'); @@ -14592,10 +14633,10 @@ async function showCertViewModal() { loading.style.display = 'none'; content.classList.remove('hidden'); } else { - throw new Error(result.message || '获取证书失败'); + throw new Error(certError(result, t('toast.getCertFailed'))); } } catch (e) { - loading.textContent = typeof t === 'function' ? t('securityPage.loadFailedMsg', { msg: e.message }) : '加载失败: ' + e.message; + loading.textContent = certText('pkiPage.loadFailedMsg', '加载失败: ' + e.message, { msg: e.message }); } } @@ -14606,27 +14647,27 @@ function hideCertViewModal() { function copyCertToClipboard() { const cert = document.getElementById('cert-view-pem').value; navigator.clipboard.writeText(cert).then(() => { - showToast(typeof t === 'function' ? t('toast.certCopied') : '证书已复制到剪贴板', 'success'); + showToast(certText('toast.certCopied', '证书已复制到剪贴板'), 'success'); }).catch(e => { - showToast(typeof t === 'function' ? t('toast.copyFailedMsg', { msg: e.message }) : '复制失败: ' + e.message, 'error'); + showToast(certText('toast.copyFailedMsg', '复制失败: ' + e.message, { msg: e.message }), 'error'); }); } async function deleteCertCredentials() { - if (!confirm(typeof t === 'function' ? t('automation.confirmDeletePKI') : '确定要删除所有 PKI 凭证吗?\n\n这将删除:\n• 私钥\n• 设备证书\n• CA 证书链\n\n此操作不可撤销!')) { + if (!confirmAction(certText('ui.confirmDeletePKI', '确定要删除所有 PKI 凭证吗?\n\n这将删除:\n• 私钥\n• 设备证书\n• CA 证书链\n\n此操作不可撤销!'))) { return; } try { const result = await api.certDelete(); - if (result.code === 0 || result.data?.success) { - showToast(typeof t === 'function' ? t('toast.pkiDeleted') : 'PKI 凭证已删除', 'success'); + if (result.code === 0) { + showToast(certText('toast.pkiDeleted', 'PKI 凭证已删除'), 'success'); await refreshCertStatus(); } else { - throw new Error(result.message || '删除失败'); + throw new Error(certError(result, t('errors.deleteFailed'))); } } catch (e) { - showToast((typeof t === 'function' ? t('toast.deleteFailedMsg', { msg: e.message }) : '删除失败: ' + e.message), 'error'); + showToast((certText('toast.deleteFailedMsg', '删除失败: ' + e.message, { msg: e.message })), 'error'); } } @@ -14657,7 +14698,7 @@ async function generateKey() { try { showToast(typeof t === 'function' ? t('toast.generatingKey') : '正在生成密钥...', 'info'); - await api.keyGenerate(id, type, comment, exportable, alias, hidden); + requireApiSuccess(await api.keyGenerate(id, type, comment, exportable, alias, hidden), 'keyGenerate'); hideGenerateKeyModal(); showToast(typeof t === 'function' ? t('toast.keyGenerated', { name: alias || id }) : `密钥 "${alias || id}" 生成成功`, 'success'); await refreshSecurityPage(); @@ -14701,22 +14742,36 @@ function formatBytes(bytes) { return (bytes / (1024 * 1024)).toFixed(1) + ' MB'; } -function showToast(message, type = 'info', duration = 3000) { - // 创建 toast 元素 +function confirmAction(message) { + if (!window.i18n?.isReady() || !message || message.includes(i18n.unavailable())) { + showToast(i18n.unavailable(), 'error'); + return false; + } + return window.confirm(message); +} + +let toastTimer = null; +let toastDeadline = 0; +let toastPriority = 0; +function showToast(message, type = 'info', duration = 3000, attempt = null) { + if (attempt && !attempt.isCurrent()) return; let toast = document.getElementById('toast'); if (!toast) { toast = document.createElement('div'); toast.id = 'toast'; document.body.appendChild(toast); } - - // 支持多行文本(将 \n 转为
) - toast.innerHTML = message.replace(/\n/g, '
'); + const priority = type === 'error' ? 2 : type === 'warning' ? 1 : 0; + // A routine success must not erase an active long warning. + if (!attempt && Date.now() < toastDeadline && toastPriority > priority && toastDeadline - Date.now() > duration) return; + clearTimeout(toastTimer); + toast.textContent = String(message ?? ''); + toast.style.whiteSpace = 'pre-wrap'; + toast.setAttribute('role', priority ? 'alert' : 'status'); toast.className = `toast toast-${type} show`; - - setTimeout(() => { - toast.classList.remove('show'); - }, duration); + toastPriority = priority; + toastDeadline = Date.now() + duration; + toastTimer = setTimeout(() => { toast.classList.remove('show'); toastDeadline = 0; }, duration); } // ========================================================================= @@ -14724,10 +14779,8 @@ function showToast(message, type = 'info', duration = 3000) { // ========================================================================= async function loadTerminalPage() { + const pageCurrent = capturePageValidity(); // 取消系统页面的订阅 - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); - } // 清理之前的终端实例 if (webTerminal) { @@ -14984,16 +15037,20 @@ async function loadTerminalPage() { // 初始化终端(标签页可见时才连接,避免后台标签抢占当前会话导致 session_closed) webTerminal = new WebTerminal('terminal-container'); - const ok = await webTerminal.init(); + const terminal = webTerminal; + const ok = await terminal.init(); + if (!pageCurrent()) return; if (ok) { function doConnect() { + if (!pageCurrent()) return; if (document.visibilityState === 'visible') { - webTerminal.connect(); + terminal.connect(); } else { document.addEventListener('visibilitychange', function handler() { + if (!pageCurrent()) { document.removeEventListener('visibilitychange', handler); return; } if (document.visibilityState === 'visible') { document.removeEventListener('visibilitychange', handler); - webTerminal.connect(); + terminal.connect(); } }); } @@ -15089,10 +15146,10 @@ function updateModalWsStatus(connected) { if (statusEl) { if (connected) { statusEl.className = 'ws-status connected'; - statusEl.title = 'WebSocket 已连接 - 实时日志'; + statusEl.title = t('promptRepair.logConnected'); } else { statusEl.className = 'ws-status connecting'; - statusEl.title = 'WebSocket 连接中...'; + statusEl.title = t('promptRepair.logDisconnected'); } } } @@ -15427,12 +15484,10 @@ document.addEventListener('DOMContentLoaded', function() { // ========================================================================= async function loadOtaPage() { + const pageCurrent = capturePageValidity(); clearInterval(refreshInterval); // 取消系统页面的订阅 - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); - } const content = document.getElementById('page-content'); content.innerHTML = ` @@ -15892,24 +15947,28 @@ async function loadOtaPage() { // 加载数据 await loadOtaData(); + if (!pageCurrent()) return; // 设置定时刷新进度 refreshInterval = setInterval(refreshOtaProgress, 1000); } async function loadOtaData() { + const pageCurrent = capturePageValidity(); try { // 1. 加载 OTA 服务器地址 const serverResult = await api.call('ota.server.get'); + if (!pageCurrent()) return; if (serverResult?.code === 0 && serverResult.data?.url) { document.getElementById('ota-server-input').value = serverResult.data.url; } // 2. 加载版本信息 const versionResult = await api.call('ota.version'); + if (!pageCurrent()) return; if (versionResult?.code === 0 && versionResult.data) { const v = versionResult.data; - document.getElementById('ota-current-version').textContent = v.version || '未知'; + document.getElementById('ota-current-version').textContent = v.version || t('common.unknown'); document.getElementById('ota-version-meta').textContent = `${v.project || 'TianshanOS'} · ${v.compile_date || ''} ${v.compile_time || ''} · IDF ${v.idf_version || ''}`; currentFirmwareVersion = v; @@ -15917,14 +15976,17 @@ async function loadOtaData() { // 3. 加载分区信息 const partResult = await api.call('ota.partitions'); + if (!pageCurrent()) return; if (partResult?.code === 0 && partResult.data) { displayPartitionsCompact(partResult.data); } // 4. 检查当前升级状态 await refreshOtaProgress(); + if (!pageCurrent()) return; } catch (error) { + if (!pageCurrent()) return; console.error('Failed to load OTA data:', error); } } @@ -15967,7 +16029,7 @@ function displayPartitionsCompact(data) { ${p.label} ${p.is_bootable ? t('ota.partitionBootable') : t('ota.partitionIdle')} -
${hasVersion ? p.version : (p.is_bootable ? '上一版本' : '无固件')}
+
${hasVersion ? p.version : (p.is_bootable ? t('otaPage.prevVersion') : t('otaPage.noFirmware'))}
0x${p.address.toString(16).toUpperCase().padStart(8,'0')} · ${formatSize(p.size)}
@@ -15981,7 +16043,7 @@ function displayPartitionsCompact(data) { ` : `
- ${p.is_bootable ? '此分区固件无法回滚(可能已损坏)' : '此分区为空,升级后将写入新固件'} + ${p.is_bootable ? t('otaPage.cannotRollback') : t('otaPage.partitionEmpty')}
`} @@ -15993,7 +16055,9 @@ function displayPartitionsCompact(data) { } async function refreshOtaInfo() { + const pageCurrent = capturePageValidity(); await loadOtaData(); + if (!pageCurrent()) return; } // OTA 两步升级状态 @@ -16012,7 +16076,7 @@ function inferSdcardWwwPath(source) { async function resolveSdcardOtaPaths(input, includeWww) { const source = input.trim(); if (!source) { - throw new Error('请输入文件或目录路径'); + throw new Error(t('promptRepair.enterOtaPath')); } if (source.match(/\.bin$/i)) { @@ -16028,14 +16092,14 @@ async function resolveSdcardOtaPaths(input, includeWww) { const firmwareInfo = await api.storageInfo(source); if (firmwareInfo.code !== 0 || firmwareInfo.data?.type !== 'file') { - throw new Error(`未找到固件文件: ${source}`); + throw new Error(t('promptRepair.firmwareMissing', {path: source})); } const wwwPath = inferSdcardWwwPath(source); if (includeWww) { const wwwInfo = await api.storageInfo(wwwPath); if (wwwInfo.code !== 0 || wwwInfo.data?.type !== 'file') { - throw new Error(`未找到 WebUI 文件: ${wwwPath}`); + throw new Error(t('promptRepair.wwwMissing', {path: wwwPath})); } } @@ -16045,7 +16109,7 @@ async function resolveSdcardOtaPaths(input, includeWww) { const dir = source.replace(/\/+$/, '') || '/sdcard'; const list = await api.storageList(dir); if (list.code !== 0 || !Array.isArray(list.data?.entries)) { - throw new Error(`无法读取目录: ${dir}`); + throw new Error(t('promptRepair.directoryUnreadable', {path: dir})); } const files = list.data.entries.filter(entry => entry.type === 'file'); @@ -16054,14 +16118,14 @@ async function resolveSdcardOtaPaths(input, includeWww) { files.find(entry => entry.name.toLowerCase().endsWith('.bin') && entry.name.toLowerCase() !== 'www.bin'); if (!firmware) { - throw new Error(`目录中未找到固件 .bin: ${dir}`); + throw new Error(t('promptRepair.firmwareDirMissing', {path: dir})); } let wwwPath = ''; if (includeWww) { const www = files.find(entry => entry.name.toLowerCase() === 'www.bin'); if (!www) { - throw new Error(`目录中未找到 WebUI 文件: ${dir}/www.bin`); + throw new Error(t('promptRepair.wwwDirMissing', {path: dir})); } wwwPath = `${dir}/${www.name}`; } @@ -16070,13 +16134,16 @@ async function resolveSdcardOtaPaths(input, includeWww) { } async function refreshOtaProgress() { + const pageCurrent = capturePageValidity(); try { // 根据当前步骤获取不同的进度 let result; if (otaStep === 'www') { result = await api.call('ota.www.progress'); + if (!pageCurrent()) return; } else { result = await api.call('ota.progress'); + if (!pageCurrent()) return; } if (result.code === 0 && result.data) { @@ -16089,14 +16156,14 @@ async function refreshOtaProgress() { // 更新状态文本 const stateMap = { - 'idle': '空闲', - 'checking': '检查更新中...', - 'downloading': otaStep === 'www' ? '下载 WebUI...' : '下载固件...', - 'verifying': '验证中...', - 'writing': otaStep === 'www' ? '写入 WebUI...' : '写入闪存...', - 'pending_reboot': '等待重启', - 'completed': otaStep === 'www' ? 'WebUI 完成' : '固件完成', - 'error': '错误' + 'idle': t('status.idle'), + 'checking': t('otaPage.stateChecking'), + 'downloading': otaStep === 'www' ? t('otaPage.downloadingWebUI') : t('otaPage.downloadingFirmware'), + 'verifying': t('otaPage.stateVerifying'), + 'writing': otaStep === 'www' ? t('otaPage.writingWebUI') : t('otaPage.writingFlash'), + 'pending_reboot': t('otaPage.statePendingReboot'), + 'completed': otaStep === 'www' ? t('otaPage.completedWebUI') : t('otaPage.completedFirmware'), + 'error': t('common.error') }; const stateEl = document.getElementById('ota-state-text'); @@ -16106,7 +16173,7 @@ async function refreshOtaProgress() { if (!stateEl || !progressSection) return; // 显示当前步骤 - const stepText = otaStep === 'www' ? '[2/2] WebUI ' : (wwwOtaEnabled ? '[1/2] 固件 ' : ''); + const stepText = otaStep === 'www' ? '[2/2] WebUI ' : (wwwOtaEnabled ? t('promptRepair.firmwareStep') : ''); stateEl.textContent = stepText + (stateMap[state] || state); if (state !== 'idle') { @@ -16130,8 +16197,9 @@ async function refreshOtaProgress() { // 处理 App OTA 完成 - 开始 WWW OTA if (otaStep === 'app' && (state === 'pending_reboot' || state === 'completed') && wwwOtaEnabled) { - stateEl.textContent = typeof t === 'function' ? t('otaPage.firmwareUpgradeComplete') : '固件升级完成,准备升级 WebUI...'; + stateEl.textContent = typeof t === 'function' ? t('ui.firmwareUpgradeComplete') : '固件升级完成,准备升级 WebUI...'; await startWwwOta(); + if (!pageCurrent()) return; return; } @@ -16143,19 +16211,21 @@ async function refreshOtaProgress() { otaStep = 'idle'; // 显示重启倒计时 - stateEl.textContent = typeof t === 'function' ? t('otaPage.allUpgradeComplete') : '全部升级完成'; + stateEl.textContent = typeof t === 'function' ? t('ui.allUpgradeComplete') : '全部升级完成'; document.getElementById('ota-message').innerHTML = `
-

固件和 WebUI 升级完成,设备正在重启...

-

正在触发重启...

+

${t('otaPage.upgradeCompleteRebooting')}

+

${t('otaPage.triggeringReboot')}

`; // 触发设备重启 try { - await api.call('system.reboot', { delay: 1 }); + requireApiSuccess(await api.call('system.reboot', { delay: 1 }), 'call'); + if (!pageCurrent()) return; } catch (e) { - console.log('Reboot triggered (connection may have closed)'); + if (!pageCurrent()) return; + showToast(t('promptRepair.rebootUnknown'), 'warning', 10000); } // 开始检测设备重启 @@ -16174,6 +16244,7 @@ async function refreshOtaProgress() { } } } catch (error) { + if (!pageCurrent()) return; console.error('Failed to get OTA status:', error); } } @@ -16218,7 +16289,7 @@ async function startWwwOta() { otaStep = 'www'; - document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.step2Webui') : '[2/2] 开始升级 WebUI...'; + document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('ui.step2Webui') : '[2/2] 开始升级 WebUI...'; document.getElementById('ota-progress-bar').style.width = '0%'; document.getElementById('ota-progress-percent').textContent = '0%'; document.getElementById('ota-message').textContent = wwwSource; @@ -16247,9 +16318,9 @@ async function startWwwOta() { document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.stateError') : '错误'; document.getElementById('ota-message').innerHTML = `
-

固件已写入,但 WebUI 升级失败,已停止重启。

-

${result.message || '请确认 www.bin 与固件在同一目录后重试'}

- +

${t('promptRepair.wwwPartial')}

+

${escapeHtml(result.message || t('promptRepair.wwwSibling'))}

+
`; document.getElementById('ota-abort-btn').style.display = 'none'; @@ -16266,7 +16337,7 @@ async function startWwwOta() { console.error('Failed to start WWW OTA:', error); otaStep = 'idle'; document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.stateError') : '错误'; - document.getElementById('ota-message').textContent = error.message || 'WebUI 升级启动失败'; + document.getElementById('ota-message').textContent = error.message || t('toast.webuiUpgradeStartFailed'); document.getElementById('ota-abort-btn').style.display = 'none'; } } @@ -16297,12 +16368,12 @@ function startRebootDetection() { clearInterval(rebootCheckInterval); rebootCheckInterval = null; - const newVersion = result.data?.version || '未知'; + const newVersion = result.data?.version || t('common.unknown'); if (countdownEl) { countdownEl.innerHTML = ` - 设备已恢复! -
当前版本: ${newVersion} + ${t('otaPage.deviceRecovered')} +
${t('ota.currentVersion')}: ${newVersion} `; } @@ -16386,13 +16457,13 @@ async function otaFromUrl() { showToast(typeof t === 'function' ? t('toast.upgradeStartFailedMsg', { msg: result.message }) : '启动升级失败: ' + result.message, 'error'); // 显示错误状态 document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.stateError') : '错误'; - document.getElementById('ota-message').textContent = result.message || '启动失败'; + document.getElementById('ota-message').textContent = result.message || t('promptRepair.startFailed'); document.getElementById('ota-abort-btn').style.display = 'none'; } } catch (error) { showToast(typeof t === 'function' ? t('toast.upgradeStartFailedMsg', { msg: error.message }) : '启动升级失败: ' + error.message, 'error'); document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.stateError') : '错误'; - document.getElementById('ota-message').textContent = error.message || '网络错误'; + document.getElementById('ota-message').textContent = error.message || t('login.networkError'); document.getElementById('ota-abort-btn').style.display = 'none'; } } @@ -16410,7 +16481,7 @@ async function otaFromFile() { try { paths = await resolveSdcardOtaPaths(inputPath, includeWww); } catch (error) { - showToast(error.message || '无法解析 SD 卡升级文件', 'error'); + showToast(error.message || t('promptRepair.otaPathFailed'), 'error'); return; } @@ -16451,19 +16522,19 @@ async function otaFromFile() { } else { showToast(typeof t === 'function' ? t('toast.upgradeStartFailedMsg', { msg: result.message }) : '启动升级失败: ' + result.message, 'error'); document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.stateError') : '错误'; - document.getElementById('ota-message').textContent = result.message || '启动失败'; + document.getElementById('ota-message').textContent = result.message || t('promptRepair.startFailed'); document.getElementById('ota-abort-btn').style.display = 'none'; } } catch (error) { showToast(typeof t === 'function' ? t('toast.upgradeStartFailedMsg', { msg: error.message }) : '启动升级失败: ' + error.message, 'error'); document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.stateError') : '错误'; - document.getElementById('ota-message').textContent = error.message || '网络错误'; + document.getElementById('ota-message').textContent = error.message || t('login.networkError'); document.getElementById('ota-abort-btn').style.display = 'none'; } } async function validateOta() { - if (!confirm(typeof t === 'function' ? t('automation.confirmMarkFirmwareValid') : '确认将当前固件标记为有效?\n这将取消自动回滚保护。')) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmMarkFirmwareValid') : '确认将当前固件标记为有效?\n这将取消自动回滚保护。')) { return; } @@ -16482,7 +16553,7 @@ async function validateOta() { } function confirmRollback() { - if (!confirm(typeof t === 'function' ? t('automation.confirmRollback') : '确认回滚到上一版本固件?\n\n系统将立即重启并加载上一个分区的固件。\n请确保上一版本固件可用!')) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmRollback') : '确认回滚到上一版本固件?\n\n系统将立即重启并加载上一个分区的固件。\n请确保上一版本固件可用!')) { return; } @@ -16506,7 +16577,7 @@ async function rollbackOta() { } async function abortOta() { - if (!confirm(typeof t === 'function' ? t('automation.confirmAbortUpgrade') : '确认中止当前升级?')) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmAbortUpgrade') : '确认中止当前升级?')) { return; } @@ -16663,7 +16734,7 @@ async function checkForUpdates() { const statusDiv = document.getElementById('ota-update-status'); statusDiv.style.display = 'block'; statusDiv.className = 'ota-update-status'; - statusDiv.innerHTML = '

正在检查更新...

'; + statusDiv.innerHTML = ("

" + t('otaPage.checking') + "

"); try { // 尝试通过设备测试连接(如果 API 存在) @@ -16675,13 +16746,13 @@ async function checkForUpdates() { console.log('Device connection test result:', testData); if (!testData.dns_ok) { - throw new Error(`设备 DNS 解析失败: ${testData.host}`); + throw new Error(t('promptRepair.dnsFailed', {host: testData.host})); } if (!testData.tcp_ok) { - throw new Error(`设备 TCP 连接失败: ${testData.resolved_ip}:${testData.port}`); + throw new Error(t('promptRepair.tcpFailed', {host: testData.resolved_ip, port: testData.port})); } if (!testData.http_ok) { - throw new Error(`设备 HTTP 请求失败: ${testData.http_error || '无响应'}`); + throw new Error(t('promptRepair.httpFailed', {message: testData.http_error || t('common.noResponse')})); } console.log(`Device connectivity OK: DNS=${testData.dns_time_ms}ms, TCP=${testData.tcp_time_ms}ms, HTTP=${testData.http_time_ms}ms`); } @@ -16696,7 +16767,7 @@ async function checkForUpdates() { const response = await fetch(versionUrl); if (!response.ok) { - throw new Error(`服务器响应错误: ${response.status}`); + throw new Error(t('promptRepair.httpStatus', {status: response.status})); } const serverInfo = await response.json(); @@ -16752,7 +16823,7 @@ async function checkForUpdates() { `; @@ -16767,7 +16838,7 @@ async function checkForUpdates() { `; @@ -16787,7 +16858,7 @@ async function checkForUpdates() { statusDiv.innerHTML = `
${typeof t === 'function' ? t('otaPage.checkUpdateFailed') : '检查更新失败'} -
${error.message}
+
${escapeHtml(error.message)}
`; } @@ -16803,10 +16874,10 @@ async function upgradeFromServer() { // 立即显示进度区域,给用户即时反馈 const progressSection = document.getElementById('ota-progress-section'); progressSection.style.display = 'block'; - document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('otaPage.preparingUpgrade') : 'Preparing upgrade...'; + document.getElementById('ota-state-text').textContent = typeof t === 'function' ? t('ui.preparingUpgrade') : 'Preparing upgrade...'; document.getElementById('ota-progress-bar').style.width = '0%'; document.getElementById('ota-progress-percent').textContent = ''; - document.getElementById('ota-progress-size').textContent = typeof t === 'function' ? t('otaPage.initializing') : '正在初始化...'; + document.getElementById('ota-progress-size').textContent = typeof t === 'function' ? t('ui.initializing') : '正在初始化...'; document.getElementById('ota-message').textContent = serverUrl; document.getElementById('ota-abort-btn').style.display = 'none'; @@ -16851,12 +16922,12 @@ async function upgradeViaProxy(serverUrl) { try { // ===== 第一步:浏览器下载固件 ===== - updateStep(1, '下载固件中...'); + updateStep(1, t('promptRepair.firmwareDownloading')); const firmwareUrl = serverUrl.replace(/\/$/, '') + '/firmware'; - messageEl.textContent = typeof t === 'function' ? t('otaPage.downloadingFromServer') : '从 OTA 服务器下载'; + messageEl.textContent = typeof t === 'function' ? t('ui.downloadingFromServer') : '从 OTA 服务器下载'; progressBar.style.width = '0%'; progressPercent.textContent = '0%'; - progressSize.textContent = typeof t === 'function' ? t('otaPage.connectingServer') : '正在连接服务器...'; + progressSize.textContent = typeof t === 'function' ? t('ui.connectingServer') : '正在连接服务器...'; abortBtn.style.display = 'none'; // 浏览器下载阶段暂不支持中止 console.log('Proxy OTA: Downloading firmware from', firmwareUrl); @@ -16873,7 +16944,7 @@ async function upgradeViaProxy(serverUrl) { showToast(typeof t === 'function' ? t('ota.firmwareDownloadComplete', { size: formatSize(firmwareData.byteLength) }) : `固件下载完成 (${formatSize(firmwareData.byteLength)})`, 'success'); // ===== 第二步:上传固件到 ESP32 ===== - updateStep(2, '上传固件到设备...'); + updateStep(2, t('otaPage.uploadingFirmware')); messageEl.textContent = typeof t === 'function' ? t('ui.firmwareSize') + ': ' + formatSize(firmwareData.byteLength) : `固件大小: ${formatSize(firmwareData.byteLength)}`; progressBar.style.width = '0%'; progressPercent.textContent = ''; @@ -16884,7 +16955,7 @@ async function upgradeViaProxy(serverUrl) { const uploadResult = await uploadFirmwareToDevice(firmwareData, false); if (!uploadResult.success) { - throw new Error(uploadResult.error || '上传固件失败'); + throw new Error(uploadResult.error || t('otaPage.uploadFirmwareFailed')); } console.log('Proxy OTA: Firmware uploaded to device'); @@ -16894,9 +16965,9 @@ async function upgradeViaProxy(serverUrl) { // ===== 第三步:处理 WebUI(如果启用)===== if (includeWww) { - updateStep(3, '下载 WebUI...'); + updateStep(3, t('otaPage.downloadingWebUI')); const wwwUrl = serverUrl.replace(/\/$/, '') + '/www.bin'; - messageEl.textContent = typeof t === 'function' ? t('otaPage.downloadingFromServer') : '从 OTA 服务器下载'; + messageEl.textContent = typeof t === 'function' ? t('ui.downloadingFromServer') : '从 OTA 服务器下载'; progressBar.style.width = '0%'; progressPercent.textContent = '0%'; progressSize.textContent = typeof t === 'function' ? t('otaPage.connecting') : '正在连接...'; @@ -16914,16 +16985,16 @@ async function upgradeViaProxy(serverUrl) { showToast(typeof t === 'function' ? t('ota.webuiDownloadComplete', { size: formatSize(wwwData.byteLength) }) : `WebUI 下载完成 (${formatSize(wwwData.byteLength)})`, 'success'); // 上传 www.bin - updateStep(4, '上传 WebUI 到设备...'); + updateStep(4, t('otaPage.uploadingWebUI')); messageEl.textContent = typeof t === 'function' ? t('ui.webuiSize') + ': ' + formatSize(wwwData.byteLength) : `WebUI 大小: ${formatSize(wwwData.byteLength)}`; progressBar.style.width = '0%'; progressPercent.textContent = ''; - progressSize.textContent = typeof t === 'function' ? t('otaPage.writingSpiffs') : '正在写入 SPIFFS...'; + progressSize.textContent = typeof t === 'function' ? t('ui.writingSpiffs') : '正在写入 SPIFFS...'; const wwwResult = await uploadWwwToDevice(wwwData); if (!wwwResult.success) { - throw new Error(wwwResult.error || 'WebUI 上传失败'); + throw new Error(wwwResult.error || t('promptRepair.webUploadFailed')); } console.log('Proxy OTA: WWW uploaded to device'); @@ -16932,19 +17003,19 @@ async function upgradeViaProxy(serverUrl) { progressPercent.textContent = ''; } catch (wwwError) { console.warn('WWW download/upload failed:', wwwError); - throw new Error('WebUI 升级失败: ' + (wwwError.message || wwwError)); + throw new Error(t('promptRepair.webUpgradeFailed') + (wwwError.message || wwwError)); } } // ===== 最终步骤:升级完成,触发重启 ===== - stateEl.textContent = typeof t === 'function' ? t('otaPage.allUpgradeComplete') : '全部升级完成'; + stateEl.textContent = typeof t === 'function' ? t('ui.allUpgradeComplete') : '全部升级完成'; progressBar.style.width = '100%'; progressBar.style.background = 'linear-gradient(90deg, #059669, #10b981)'; progressPercent.textContent = ''; messageEl.innerHTML = `
-

固件${includeWww ? '和 WebUI ' : ''}升级完成,设备正在重启...

-

正在触发重启...

+

${t('promptRepair.upgradeWritten')}

+

${t('otaPage.triggeringReboot')}

`; @@ -16952,9 +17023,9 @@ async function upgradeViaProxy(serverUrl) { // 触发设备重启 try { - await api.call('system.reboot', { delay: 1 }); + requireApiSuccess(await api.call('system.reboot', { delay: 1 }), 'call'); } catch (e) { - console.log('Reboot triggered (connection may have closed)'); + showToast(t('promptRepair.rebootUnknown'), 'warning', 10000); } // 检测设备重启 @@ -16962,7 +17033,7 @@ async function upgradeViaProxy(serverUrl) { } catch (error) { console.error('Proxy OTA failed:', error); - stateEl.textContent = typeof t === 'function' ? t('otaPage.upgradeFailed') : '升级失败'; + stateEl.textContent = typeof t === 'function' ? t('ui.upgradeFailed') : '升级失败'; messageEl.textContent = error.message; progressBar.style.width = '0%'; progressPercent.textContent = ''; @@ -16977,7 +17048,7 @@ async function upgradeViaProxy(serverUrl) { async function downloadWithProgress(url, onProgress) { const response = await fetch(url); if (!response.ok) { - throw new Error(`下载失败: HTTP ${response.status}`); + throw new Error(t('promptRepair.downloadHttpStatus', {status: response.status})); } const contentLength = response.headers.get('content-length'); @@ -17030,7 +17101,7 @@ async function uploadFirmwareToDevice(firmwareData, autoReboot = false) { if (response.ok && result.status === 'success') { return { success: true, data: result }; } else { - return { success: false, error: result.message || result.error || '上传失败' }; + return { success: false, error: result.message || result.error || t('files.uploadFailed') }; } } catch (error) { return { success: false, error: error.message }; @@ -17057,7 +17128,7 @@ async function uploadWwwToDevice(wwwData) { if (response.ok && result.status === 'success') { return { success: true, data: result }; } else { - return { success: false, error: result.message || result.error || '上传失败' }; + return { success: false, error: result.message || result.error || t('files.uploadFailed') }; } } catch (error) { return { success: false, error: error.message }; @@ -17100,6 +17171,15 @@ let cachedTasksData = []; // 缓存任务数据用于排序 /** * 渲染任务行 HTML */ +function servicePhaseLabel(phase) { + return ["PLATFORM", "CORE", "HAL", "DRIVER", "NETWORK", "SECURITY", "SERVICE", "UI"].includes(phase) ? t('promptRepair.phase_' + phase) : t('common.unknown'); +} + +function userStateLabel(state) { + const known = ["UNREGISTERED", "REGISTERED", "STARTING", "RUNNING", "STOPPING", "STOPPED", "ERROR", "Running", "Ready", "Blocked", "Suspended", "Deleted"]; + return known.includes(state) ? t('promptRepair.state_' + state) : t('common.unknown'); +} + function renderTaskRows(tasks, formatBytes) { return tasks.map(task => { const hwm = task.stack_hwm || 0; @@ -17123,7 +17203,7 @@ function renderTaskRows(tasks, formatBytes) { ${formatBytes(hwm)} ${usagePct}% ${task.priority} - ${stateIcon} ${task.state} + ${stateIcon} ${userStateLabel(task.state)} ${task.cpu_percent !== undefined ? `${task.cpu_percent}%` : ''} `; @@ -17590,7 +17670,7 @@ async function refreshMemoryDetail() { body.innerHTML = `

${typeof t === 'function' ? t('memoryPage.loadFailed') : '获取内存详情失败'}

-

${error.message}

+

${escapeHtml(error.message)}

`; } @@ -17619,10 +17699,8 @@ window.refreshMemoryDetail = refreshMemoryDetail; * 加载自动化引擎测试页面 */ async function loadAutomationPage() { + const pageCurrent = capturePageValidity(); // 取消之前的订阅 - if (subscriptionManager) { - subscriptionManager.unsubscribe('system.dashboard'); - } stopServiceStatusRefresh(); const content = document.getElementById('page-content'); @@ -17648,7 +17726,7 @@ async function loadAutomationPage() {

${t('automation.sources')}

- +
@@ -17665,7 +17743,7 @@ async function loadAutomationPage() {

${t('automation.rules')}

- +
@@ -17682,7 +17760,7 @@ async function loadAutomationPage() {

${t('automation.actions')}

- +
@@ -17702,17 +17780,20 @@ async function loadAutomationPage() { refreshSources(), refreshActions() ]); + if (!pageCurrent()) return; } /** * 刷新自动化引擎状态 */ async function refreshAutomationStatus() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('automation-status'); if (!container) return; try { const result = await api.call('automation.status'); + if (!pageCurrent()) return; if (result.code === 0 && result.data) { const d = result.data; const stateClass = d.state === 'running' ? 'running' : d.state === 'paused' ? 'paused' : 'stopped'; @@ -17763,6 +17844,7 @@ async function refreshAutomationStatus() { container.innerHTML = '
' + (result.message || (typeof t === 'function' ? t('automationPage.getStatusFailed') : '获取状态失败')) + '
'; } } catch (error) { + if (!pageCurrent()) return; const isNetworkError = error.message.includes('fetch') || error.message.includes('network'); container.innerHTML = '
' + (isNetworkError && typeof t === 'function' ? t('automationPage.networkFailed') : error.message) + '
'; } @@ -17779,11 +17861,11 @@ function formatUptimeSec(seconds) { const m = Math.floor((seconds % 3600) / 60); return t('automationPage.uptimeHrMin', { h, m }); } - if (seconds < 60) return seconds + '秒'; - if (seconds < 3600) return Math.floor(seconds / 60) + '分' + (seconds % 60) + '秒'; + if (seconds < 60) return seconds + t('common.seconds'); + if (seconds < 3600) return Math.floor(seconds / 60) + t('common.minutesShort') + (seconds % 60) + t('common.seconds'); const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); - return h + '时' + m + '分'; + return h + t('common.hoursShort') + m + t('common.minutesShort'); } /** @@ -17805,11 +17887,13 @@ async function automationControl(action) { * 刷新规则列表 */ async function refreshRules() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('rules-list'); if (!container) return; try { const result = await api.call('automation.rules.list'); + if (!pageCurrent()) return; if (result.code === 0 && result.data && result.data.rules) { const rules = result.data.rules; if (rules.length === 0) { @@ -17824,12 +17908,12 @@ async function refreshRules() { ID - ${ap('automationPage.ruleNameHeader') || '名称'} - ${ap('automationPage.statusHeader') || '状态'} - ${ap('automationPage.conditionHeader') || '条件'} - ${ap('automationPage.actionHeader') || '动作'} - ${ap('automationPage.triggerHeader') || '触发次数'} - ${ap('automationPage.operationHeader') || '操作'} + ${ap('automationPage.ruleNameHeader') || t('common.name')} + ${ap('automationPage.statusHeader') || t('common.status')} + ${ap('automationPage.conditionHeader') || t('automationPage.conditionHeader')} + ${ap('automationPage.actionHeader') || t('automationPage.actionHeader')} + ${ap('automationPage.triggerHeader') || t('automation.triggerCount')} + ${ap('automationPage.operationHeader') || t('common.actions')} @@ -17871,6 +17955,7 @@ async function refreshRules() { container.innerHTML = '

' + (result.message || (typeof t === 'function' ? t('automationPage.getRulesFailed') : '获取规则失败')) + '

'; } } catch (error) { + if (!pageCurrent()) return; const isNetworkError = error.message.includes('fetch') || error.message.includes('network'); container.innerHTML = '

' + (isNetworkError && typeof t === 'function' ? t('automationPage.networkFailed') : error.message) + '

'; } @@ -17882,7 +17967,7 @@ async function refreshRules() { async function toggleRule(id, enable) { try { const action = enable ? 'automation.rules.enable' : 'automation.rules.disable'; - const result = await api.call(action, { id }); + const result = await ruleWriteWithRevision(action, id); showToast(typeof t === 'function' ? t('toast.ruleToggled', { id, state: enable ? t('status.enabled') : t('status.disabled') }) + ': ' + (result.message || 'OK') : `规则 ${id} ${enable ? '启用' : '禁用'}: ${result.message || 'OK'}`, result.code === 0 ? 'success' : 'error'); if (result.code === 0) { await refreshRules(); @@ -17908,11 +17993,13 @@ async function triggerRule(id) { * 刷新数据源列表 */ async function refreshSources() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('sources-list'); if (!container) return; try { const result = await api.call('automation.sources.list'); + if (!pageCurrent()) return; if (result.code === 0 && result.data && result.data.sources) { const sources = result.data.sources; if (sources.length === 0) { @@ -17958,6 +18045,7 @@ async function refreshSources() { container.innerHTML = '

' + (result.message || (typeof t === 'function' ? t('automationPage.getSourcesFailed') : '获取数据源失败')) + '

'; } } catch (error) { + if (!pageCurrent()) return; const isNetworkError = error.message.includes('fetch') || error.message.includes('network'); container.innerHTML = '

' + (isNetworkError && typeof t === 'function' ? t('automationPage.networkFailed') : error.message) + '

'; } @@ -17970,6 +18058,7 @@ let allVariables = []; * 刷新变量列表 */ async function refreshVariables() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('variables-list'); const countBadge = document.getElementById('variables-count'); if (!container) return; @@ -17978,15 +18067,17 @@ async function refreshVariables() { try { const result = await api.call('automation.variables.list', { include_meta: true }); + if (!pageCurrent()) return; if (result.code === 0 && result.data && result.data.variables) { allVariables = result.data.variables; if (countBadge) countBadge.textContent = allVariables.length; renderVariables(allVariables); } else { - container.innerHTML = `

${result.message || (typeof t === 'function' ? t('sshPage.getVarFailed') : '获取变量失败')}

`; + container.innerHTML = `

${escapeHtml(result.message || (typeof t === 'function' ? t('sshPage.getVarFailed') : '获取变量失败'))}

`; } } catch (error) { - container.innerHTML = `

${error.message}

`; + if (!pageCurrent()) return; + container.innerHTML = `

${escapeHtml(error.message)}

`; } } @@ -18032,7 +18123,7 @@ function renderVariables(variables) {
${source} - ${vars.length} 个变量 + ${t('promptRepair.variableCount', {count: vars.length})}
@@ -18140,11 +18231,13 @@ function escapeHtml(text) { * 刷新动作模板列表 */ async function refreshActions() { + const pageCurrent = capturePageValidity(); const container = document.getElementById('actions-list'); if (!container) return; try { const result = await api.call('automation.actions.list', {}); + if (!pageCurrent()) return; const actions = result.data?.templates || []; if (actions.length === 0) { @@ -18185,6 +18278,7 @@ async function refreshActions() { `; } } catch (error) { + if (!pageCurrent()) return; container.innerHTML = '

' + (typeof t === 'function' ? t('filePage.loadFailed') : '加载失败') + ': ' + error.message + '

'; } } @@ -18198,9 +18292,9 @@ function getActionTypeLabel(type) { 'ssh_cmd': 'SSH', 'gpio': 'GPIO', 'webhook': 'Webhook', - 'log': '日志', - 'set_var': '变量', - 'device_ctrl': '设备' + 'log': t('common.log'), + 'set_var': t('common.variable'), + 'device_ctrl': t('common.devices') }; return labels[type] || type; } @@ -18323,7 +18417,7 @@ function showAddActionModal() { `; @@ -18358,14 +18452,14 @@ function updateActionTypeFields() { ${typeof t === 'function' ? t('automation.cliConfig') : 'CLI 命令配置'}
- + ${typeof t === 'function' ? t('automation.cliCmdHint') : '支持所有控制台命令: gpio, device, fan, led, net 等'}
${typeof t === 'function' ? t('automation.quickCommands') : '快捷命令:'} - + @@ -18396,16 +18490,16 @@ function updateActionTypeFields() { ${typeof t === 'function' ? t('automation.sshCmdConfig') : 'SSH 命令配置'}
- + ${typeof t === 'function' ? t('automation.sshCmdHint') : '选择已在 SSH 管理页面配置的命令'}
- + ${typeof t === 'function' ? t('automation.selectLedDeviceHint') : '选择要控制的 LED 设备'}
@@ -18462,11 +18556,11 @@ function updateActionTypeFields() {
- ${typeof t === 'function' ? t('automation.logConfig') : '日志配置'} + ${typeof t === 'function' ? t('automationPage.logConfig') : '日志配置'}
- + - ${typeof t === 'function' ? t('automation.logMsgHint') : '支持变量: ${变量名}'} + + + ${typeof t === 'function' ? t('automationPage.logMsgHint') : '支持变量: ${变量名}'}
`, @@ -18486,16 +18580,16 @@ function updateActionTypeFields() {
- ${typeof t === 'function' ? t('automation.varConfig') : '变量配置'} + ${typeof t === 'function' ? t('automationPage.varConfig') : '变量配置'}
- - + +
- - - 示例: true, 123, \${other_var} + + + ${t('promptRepair.valueExample')}
`, @@ -18503,7 +18597,7 @@ function updateActionTypeFields() {
- Webhook 配置 + ${t('promptRepair.webhookConfig')}
@@ -18511,7 +18605,7 @@ function updateActionTypeFields() {
- + - JSON 格式,支持变量 + ${t('automationPage.requestBodyHint')}
` @@ -18758,7 +18852,7 @@ async function loadSshHostsForAction() { if (!select) return; const result = await api.call('ssh.hosts.list', {}); - select.innerHTML = ''; + select.innerHTML = (""); if (result.code === 0 && result.data?.hosts) { result.data.hosts.forEach(host => { @@ -18771,7 +18865,7 @@ async function loadSshHostsForAction() { if (select.options.length === 1) { // 没有配置主机,提示用户 - select.innerHTML = ''; + select.innerHTML = (""); } } catch (e) { console.error('加载 SSH 主机列表失败:', e); @@ -18791,7 +18885,7 @@ async function loadSshCommandsForAction() { if (!select) return; const result = await api.call('ssh.commands.list', {}); - select.innerHTML = ''; + select.innerHTML = (""); if (result.code === 0 && result.data?.commands) { result.data.commands.forEach(cmd => { @@ -18834,7 +18928,7 @@ async function updateSshCmdRefPreview() { document.getElementById('preview-cmd').textContent = cmd.command || '-'; // varName 字段只在配置了变量名时才存在 const varName = cmd.varName || cmd.var_name || ''; - document.getElementById('preview-var').textContent = varName || '(未配置)'; + document.getElementById('preview-var').textContent = varName || t('ui.configNotSet'); preview.style.display = 'block'; } else { preview.style.display = 'none'; @@ -18855,7 +18949,7 @@ async function loadLedDevicesForAction() { if (!select) return; const result = await api.ledList(); - select.innerHTML = ''; + select.innerHTML = (""); if (result.data?.devices) { result.data.devices.forEach(dev => { @@ -18953,8 +19047,8 @@ function updateActionLedTypeFields() {
- - + +
`; @@ -18998,24 +19092,24 @@ function updateActionLedTypeFields() { break; case 'off': - html = `
${typeof t === 'function' ? t('automation.ledOffHint') : '关闭 LED 设备,无需额外参数'}
`; + html = `
${typeof t === 'function' ? t('automationPage.ledOffHint') : '关闭 LED 设备,无需额外参数'}
`; break; case 'filter_stop': - html = `
${typeof t === 'function' ? t('automation.filterStopHint') : '停止当前运行的滤镜效果,无需额外参数'}
`; + html = `
${typeof t === 'function' ? t('automationPage.filterStopHint') : '停止当前运行的滤镜效果,无需额外参数'}
`; break; case 'text_stop': - html = `
${typeof t === 'function' ? t('automation.textStopHint') : '停止当前运行的文本覆盖层,无需额外参数'}
`; + html = `
${typeof t === 'function' ? t('automationPage.textStopHint') : '停止当前运行的文本覆盖层,无需额外参数'}
`; break; case 'text': html = `
- +
- - + +
@@ -19026,7 +19120,7 @@ function updateActionLedTypeFields() {
- +
@@ -19040,13 +19134,13 @@ function updateActionLedTypeFields() {
- +
@@ -19060,8 +19154,8 @@ function updateActionLedTypeFields() {
- - + +
@@ -19070,8 +19164,8 @@ function updateActionLedTypeFields() {
- - + +
`; @@ -19082,16 +19176,16 @@ function updateActionLedTypeFields() { case 'image': html = `
- +
- + - +
- ${typeof t === 'function' ? t('automation.imagePathHint') : '支持 PNG、JPG、BMP、GIF 格式,路径支持变量'} + ${typeof t === 'function' ? t('automationPage.imagePathHint') : '支持 PNG、JPG、BMP、GIF 格式,路径支持变量'}
- +
`; break; @@ -19099,15 +19193,15 @@ function updateActionLedTypeFields() { case 'qrcode': html = `
- +
- - + +
- +
- +
- +
- + - +
`; @@ -19134,22 +19228,22 @@ function updateActionLedTypeFields() { case 'filter': html = `
- +
@@ -19227,8 +19321,8 @@ async function showImageSelectModal(title, onSelect) { @@ -19288,8 +19382,8 @@ async function showImageSelectModal(title, onSelect) { console.error('加载图像列表失败:', e); document.getElementById('image-select-loading').innerHTML = `
-

加载失败: ${e.message}

- +

${t('common.loadFailed')}: ${escapeHtml(e.message)}

+
`; } @@ -19322,7 +19416,7 @@ function selectImageItem(el, path) { * 浏览图像文件 (动作模板用) */ async function browseActionImages() { - showImageSelectModal('选择图像文件', (path) => { + showImageSelectModal(t('dataSource.selectImageFile'), (path) => { document.getElementById('action-led-image-path').value = path; }); } @@ -19331,7 +19425,7 @@ async function browseActionImages() { * 浏览 QR 背景图 (动作模板用) */ async function browseActionQrBg() { - showImageSelectModal('选择背景图', (path) => { + showImageSelectModal(t('dataSource.selectBgImage'), (path) => { document.getElementById('action-led-qr-bg').value = path; }); } @@ -19366,8 +19460,8 @@ async function showVariableSelectModal(targetInputId, mode = 'insert') { @@ -19456,8 +19550,8 @@ async function showVariableSelectModal(targetInputId, mode = 'insert') { console.error('加载变量列表失败:', e); document.getElementById('variable-select-loading').innerHTML = `
-

加载失败: ${e.message}

- +

${t('common.loadFailed')}: ${escapeHtml(e.message)}

+
`; } @@ -19620,7 +19714,7 @@ function updateActionFilterParams() { const config = filterConfig[filter]; if (!config || !config.params || config.params.length === 0) { - paramsContainer.innerHTML = '
此滤镜无额外参数
'; + paramsContainer.innerHTML = ("
" + t('automationPage.noExtraParams') + "
"); return; } @@ -19656,9 +19750,9 @@ async function testAction(id) { console.log('Action execute result:', result); if (result.code === 0) { - let msg = result.message || '执行成功'; + let msg = t('toast.actionSuccess'); if (result.data?.output) { - msg += ` - 输出: ${result.data.output.substring(0, 100)}`; + msg += '\n' + t('promptRepair.outputPreview', {output: result.data.output.substring(0, 100)}); } showToast(msg, 'success'); } else { @@ -19884,11 +19978,11 @@ async function editAction(id) { // 更改模态框标题和按钮 const modalTitle = document.querySelector('#action-modal .modal-header h3'); - if (modalTitle) modalTitle.textContent = typeof t === 'function' ? t('otaPage.editActionTemplate') : '编辑动作模板'; + if (modalTitle) modalTitle.textContent = typeof t === 'function' ? t('ui.editActionTemplate') : '编辑动作模板'; const submitBtn = document.querySelector('#action-modal button[onclick="submitAction()"]'); if (submitBtn) { - submitBtn.textContent = typeof t === 'function' ? t('otaPage.updateAction') : '更新'; + submitBtn.textContent = typeof t === 'function' ? t('ui.updateAction') : '更新'; submitBtn.setAttribute('onclick', `updateAction('${tpl.id}')`); } @@ -19928,7 +20022,7 @@ async function updateAction(originalId) { * 删除动作 */ async function deleteAction(id) { - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteAction', { id }) : `确定要删除动作模板 "${id}" 吗?`)) return; + if (!confirmAction(typeof t === 'function' ? t('ui.confirmDeleteAction', { id }) : `确定要删除动作模板 "${id}" 吗?`)) return; try { const result = await api.call('automation.actions.delete', { id }); @@ -19947,7 +20041,7 @@ async function deleteAction(id) { async function toggleSource(id, enable) { try { const action = enable ? 'automation.sources.enable' : 'automation.sources.disable'; - const result = await api.call(action, { id }); + const result = await ruleWriteWithRevision(action, id); showToast(typeof t === 'function' ? t('toast.sourceToggled', { id, state: enable ? t('status.enabled') : t('status.disabled') }) + ': ' + (result.message || 'OK') : `数据源 ${id} ${enable ? '启用' : '禁用'}: ${result.message || 'OK'}`, result.code === 0 ? 'success' : 'error'); if (result.code === 0) { await refreshSources(); @@ -19961,7 +20055,7 @@ async function toggleSource(id, enable) { * 删除数据源 */ async function deleteSource(id) { - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteSource', { id }) : `确定要删除数据源 "${id}" 吗?此操作不可撤销。`)) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmDeleteSource', { id }) : `确定要删除数据源 "${id}" 吗?此操作不可撤销。`)) { return; } @@ -20028,10 +20122,10 @@ async function showSourceVariables(sourceId) {
`; } else { - body.innerHTML = `

${result.message || (typeof t === 'function' ? t('sshPage.getVarFailed') : '获取变量失败')}

`; + body.innerHTML = `

${escapeHtml(result.message || (typeof t === 'function' ? t('sshPage.getVarFailed') : '获取变量失败'))}

`; } } catch (error) { - body.innerHTML = `

${error.message}

`; + body.innerHTML = `

${escapeHtml(error.message)}

`; } } @@ -20108,13 +20202,13 @@ async function saveShutdownSettings() { // 验证 if (config.low_threshold >= config.recovery_threshold) { - errorDiv.textContent = typeof t === 'function' ? t('otaPage.lowVoltageError') : '低电压阈值必须小于恢复电压阈值'; + errorDiv.textContent = typeof t === 'function' ? t('ui.lowVoltageError') : '低电压阈值必须小于恢复电压阈值'; errorDiv.classList.remove('hidden'); return; } if (config.shutdown_delay < 10 || config.shutdown_delay > 600) { - errorDiv.textContent = typeof t === 'function' ? t('otaPage.shutdownDelayError') : '关机倒计时必须在 10-600 秒之间'; + errorDiv.textContent = typeof t === 'function' ? t('ui.shutdownDelayError') : '关机倒计时必须在 10-600 秒之间'; errorDiv.classList.remove('hidden'); return; } @@ -20125,7 +20219,7 @@ async function saveShutdownSettings() { showToast(typeof t === 'function' ? t('toast.shutdownSettingsSaved') : '关机设置已保存', 'success'); closeShutdownSettingsModal(); } else { - errorDiv.textContent = result.message || '保存失败'; + errorDiv.textContent = result.message || t('errors.saveFailed'); errorDiv.classList.remove('hidden'); } } catch (e) { @@ -20138,7 +20232,7 @@ async function saveShutdownSettings() { * 恢复默认关机设置 */ async function resetShutdownSettings() { - if (!confirm(typeof t === 'function' ? t('automation.confirmRestoreDefaults') : '确认恢复默认设置?')) return; + if (!confirmAction(typeof t === 'function' ? t('ui.confirmRestoreDefaults') : '确认恢复默认设置?')) return; const config = { low_threshold: 12.6, @@ -20171,12 +20265,12 @@ async function resetShutdownSettings() { * 删除规则 */ async function deleteRule(id) { - if (!confirm(typeof t === 'function' ? t('ui.confirmDeleteRule', { id }) : `确定要删除规则 "${id}" 吗?此操作不可撤销。`)) { + if (!confirmAction(typeof t === 'function' ? t('ui.confirmDeleteRule', { id }) : `确定要删除规则 "${id}" 吗?此操作不可撤销。`)) { return; } try { - const result = await api.call('automation.rules.delete', { id }); + const result = await ruleWriteWithRevision('automation.rules.delete', id); showToast(typeof t === 'function' ? t('toast.deleteRuleResult', { id }) + ': ' + (result.message || 'OK') : `删除规则 ${id}: ${result.message || 'OK'}`, result.code === 0 ? 'success' : 'error'); if (result.code === 0) { await Promise.all([refreshRules(), refreshAutomationStatus()]); @@ -20427,7 +20521,7 @@ async function testRestConnection() { const auth = document.getElementById('source-rest-auth').value.trim(); if (!url) { - alert(typeof t === 'function' ? t('automation.alertEnterApiAddress') : '请输入 API 地址'); + alert(typeof t === 'function' ? t('ui.alertEnterApiAddress') : '请输入 API 地址'); return; } @@ -20436,9 +20530,9 @@ async function testRestConnection() { const statusSpan = resultPanel.querySelector('.test-status'); btn.disabled = true; - btn.innerHTML = ' 测试中...'; + btn.innerHTML = (" " + t('ui.testing') + ""); resultPanel.style.display = 'block'; - statusSpan.innerHTML = ' 正在请求...'; + statusSpan.innerHTML = (" " + t('automationPage.testRequesting') + ""); try { // 通过 ESP32 代理请求(避免 CORS) @@ -20450,7 +20544,7 @@ async function testRestConnection() { if (result.code === 0 && result.data) { lastTestData = result.data.body; - statusSpan.innerHTML = `连接成功 (${result.data.status || 200})`; + statusSpan.innerHTML = `${t('ssh.connectionSuccess')} (${result.data.status || 200})`; // 解析并显示可选变量 try { @@ -20460,20 +20554,20 @@ async function testRestConnection() { } catch (e) { // 非 JSON 响应 document.querySelector('#rest-var-selector .var-list').innerHTML = - '
响应非 JSON 格式,无法解析字段
'; + ("
" + t('dataSource.responseNotJson') + "
"); document.getElementById('rest-json-preview').textContent = lastTestData; } } else { - statusSpan.innerHTML = `请求失败: ${result.message || '未知错误'}`; + statusSpan.innerHTML = `${t('automationPage.testFailed')}: ${escapeHtml(result.message || t('errors.unknownError'))}`; document.querySelector('#rest-var-selector .var-list').innerHTML = ''; } } catch (error) { - statusSpan.innerHTML = `错误: ${error.message}`; + statusSpan.innerHTML = `${t('common.error')}: ${escapeHtml(error.message)}`; document.querySelector('#rest-var-selector .var-list').innerHTML = ''; } btn.disabled = false; - btn.innerHTML = ' 测试'; + btn.innerHTML = (" " + t('common.test') + ""); } /** @@ -20483,7 +20577,7 @@ async function testWsConnection() { const uri = document.getElementById('source-ws-uri').value.trim(); if (!uri) { - alert(typeof t === 'function' ? t('automation.alertEnterWsAddress') : '请输入 WebSocket 地址'); + alert(typeof t === 'function' ? t('ui.alertEnterWsAddress') : '请输入 WebSocket 地址'); return; } @@ -20498,9 +20592,9 @@ async function testWsConnection() { } btn.disabled = true; - btn.innerHTML = ' 连接中...'; + btn.innerHTML = (" " + t('network.connecting') + ""); resultPanel.style.display = 'block'; - statusSpan.innerHTML = '正在连接...'; + statusSpan.innerHTML = ("" + t('toast.connecting') + ""); try { // 通过 ESP32 测试 WebSocket(获取第一条消息) @@ -20508,7 +20602,7 @@ async function testWsConnection() { if (result.code === 0 && result.data) { lastTestData = result.data.message; - statusSpan.innerHTML = `连接成功,已收到数据`; + statusSpan.innerHTML = `${t('automationPage.testConnected')}`; try { const jsonData = typeof lastTestData === 'string' ? JSON.parse(lastTestData) : lastTestData; @@ -20516,20 +20610,20 @@ async function testWsConnection() { document.getElementById('ws-json-preview').textContent = JSON.stringify(jsonData, null, 2); } catch (e) { document.querySelector('#ws-var-selector .var-list').innerHTML = - '
消息非 JSON 格式,无法解析字段
'; + ("
" + t('dataSource.messageNotJson') + "
"); document.getElementById('ws-json-preview').textContent = lastTestData; } } else { - statusSpan.innerHTML = `${result.message || '连接失败'}`; + statusSpan.innerHTML = `${escapeHtml(result.message || t('ssh.connectionFailed'))}`; document.querySelector('#ws-var-selector .var-list').innerHTML = ''; } } catch (error) { - statusSpan.innerHTML = `错误: ${error.message}`; + statusSpan.innerHTML = `${t('common.error')}: ${escapeHtml(error.message)}`; document.querySelector('#ws-var-selector .var-list').innerHTML = ''; } btn.disabled = false; - btn.innerHTML = ' 测试'; + btn.innerHTML = (" " + t('common.test') + ""); } /** @@ -20541,7 +20635,7 @@ async function testSioConnection() { const timeout = parseInt(document.getElementById('source-sio-timeout').value) || 15000; if (!url) { - alert(typeof t === 'function' ? t('automation.alertEnterSioAddress') : '请输入 Socket.IO 服务器地址'); + alert(typeof t === 'function' ? t('ui.alertEnterSioAddress') : '请输入 Socket.IO 服务器地址'); return; } @@ -20551,12 +20645,12 @@ async function testSioConnection() { const eventInput = document.getElementById('source-sio-event'); btn.disabled = true; - btn.innerHTML = ' 连接中...'; + btn.innerHTML = (" " + t('network.connecting') + ""); resultPanel.style.display = 'block'; // 显示连接阶段状态 - const statusText = event ? `正在连接并等待事件: ${event}` : '正在连接并自动发现事件...'; - statusSpan.innerHTML = ` ${statusText}`; + const statusText = event ? t('promptRepair.waitEvent', {event}) : t('sshPage.connectingAutoDiscover'); + statusSpan.innerHTML = ` ${escapeHtml(statusText)}`; try { // 通过 ESP32 测试 Socket.IO 连接 @@ -20568,16 +20662,16 @@ async function testSioConnection() { if (result.code === 0 && result.data) { const data = result.data; - const eventName = data.event || '(未知事件)'; + const eventName = data.event || t('sshPage.unknownEvent'); lastTestData = data.data; // 显示成功状态和发现的事件 - let statusHtml = `连接成功`; + let statusHtml = `${t('ssh.connectionSuccess')}`; if (data.event) { - statusHtml += ` | 事件: ${eventName}`; + statusHtml += ` | ${t('promptRepair.event')}: ${escapeHtml(eventName)}`; } if (data.sid) { - statusHtml += ` | SID: ${data.sid.substring(0, 8)}...`; + statusHtml += ` | SID: ${escapeHtml(data.sid.substring(0, 8))}...`; } statusSpan.innerHTML = statusHtml; @@ -20594,18 +20688,18 @@ async function testSioConnection() { document.getElementById('sio-json-preview').textContent = JSON.stringify(jsonData, null, 2); } catch (e) { document.querySelector('#sio-var-selector .var-list').innerHTML = - '
事件数据非 JSON 格式,无法解析字段
'; + ("
" + t('automationPage.eventDataNotJson') + "
"); document.getElementById('sio-json-preview').textContent = String(lastTestData); } } else { // 显示详细错误信息 - let errorMsg = result.message || '连接失败'; + let errorMsg = result.message || t('ssh.connectionFailed'); if (result.data && result.data.sid) { - errorMsg += ` (已获取 SID,但未收到事件数据)`; + errorMsg += ' ' + t('promptRepair.noEvent'); } - statusSpan.innerHTML = `${errorMsg}`; + statusSpan.innerHTML = `${escapeHtml(errorMsg)}`; document.querySelector('#sio-var-selector .var-list').innerHTML = - '
提示:留空事件名称可自动发现服务器推送的事件
'; + ("
" + t('automationPage.hintAutoDiscoverEvent') + "
"); // 显示详细错误 if (result.data && result.data.error) { @@ -20614,12 +20708,12 @@ async function testSioConnection() { } } } catch (error) { - statusSpan.innerHTML = `错误: ${error.message}`; + statusSpan.innerHTML = `${t('common.error')}: ${escapeHtml(error.message)}`; document.querySelector('#sio-var-selector .var-list').innerHTML = ''; } btn.disabled = false; - btn.innerHTML = ' 测试'; + btn.innerHTML = (" " + t('common.test') + ""); } /** @@ -20641,7 +20735,7 @@ function renderVarSelector(containerId, data, targetInputId, prefix = '') { flattenJson(data, prefix, items); if (items.length === 0) { - container.innerHTML = '
无可选字段
'; + container.innerHTML = ("
" + t('ui.noSelectableFields') + "
"); return; } @@ -20824,21 +20918,21 @@ async function loadSshHostsForSource() { const hosts = result.data.hosts; if (hosts.length === 0) { - hostSelect.innerHTML = ''; + hostSelect.innerHTML = ''; return; } let html = ''; hosts.forEach(h => { const label = `${h.id} (${h.username}@${h.host}:${h.port || 22})`; - html += ``; + html += ``; }); hostSelect.innerHTML = html; } else { - hostSelect.innerHTML = ``; + hostSelect.innerHTML = ``; } } catch (error) { - hostSelect.innerHTML = ``; + hostSelect.innerHTML = ``; } } @@ -20857,7 +20951,7 @@ async function onSshHostChangeForSource() { // 重置变量预览 const varsListDiv = document.getElementById('ssh-vars-list'); - if (varsListDiv) varsListDiv.innerHTML = '请先选择指令'; + if (varsListDiv) varsListDiv.innerHTML = ("" + t('ui.selectCmdFirst') + ""); if (!hostId) { cmdSelect.innerHTML = ''; @@ -20874,11 +20968,11 @@ async function onSshHostChangeForSource() { const commands = sshCommands[hostId] || []; if (commands.length === 0) { - cmdSelect.innerHTML = ''; + cmdSelect.innerHTML = ''; return; } - let html = ''; + let html = ''; commands.forEach((cmd, idx) => { const icon = cmd.icon || 'ri-rocket-line'; const label = (icon && icon.startsWith && icon.startsWith('ri-')) ? cmd.name : `${icon} ${cmd.name}`; @@ -20900,7 +20994,7 @@ function onSshCmdChange() { if (!hostId || cmdIdx === '') { if (preview) preview.style.display = 'none'; - if (varsListDiv) varsListDiv.innerHTML = '请先选择指令'; + if (varsListDiv) varsListDiv.innerHTML = ("" + t('ui.selectCmdFirst') + ""); return; } @@ -20908,7 +21002,7 @@ function onSshCmdChange() { const cmd = sshCommands[hostId]?.[parseInt(cmdIdx)]; if (!cmd) { if (preview) preview.style.display = 'none'; - if (varsListDiv) varsListDiv.innerHTML = '指令不存在'; + if (varsListDiv) varsListDiv.innerHTML = ("" + t('ui.cmdNotExist') + ""); return; } @@ -20916,7 +21010,7 @@ function onSshCmdChange() { if (preview) { preview.style.display = 'block'; document.getElementById('preview-command').textContent = cmd.command; - document.getElementById('preview-desc').textContent = cmd.desc || '无描述'; + document.getElementById('preview-desc').textContent = cmd.desc || t('ui.noDescription'); document.getElementById('preview-timeout').textContent = cmd.timeout || 30; } @@ -20924,13 +21018,13 @@ function onSshCmdChange() { const varName = cmd.varName || cmd.name; // 优先使用 varName,否则用 name if (varsListDiv) { varsListDiv.innerHTML = ` -
${varName}.status - 执行状态 (success/failed/error)
-
${varName}.exit_code - 退出码
-
${varName}.extracted - 提取的值
-
${varName}.expect_matched - 成功模式匹配结果
-
${varName}.fail_matched - 失败模式匹配结果
-
${varName}.host - 执行主机
-
${varName}.timestamp - 执行时间戳
+
${escapeHtml(varName)}.status - ${t('varPreview.status')}
+
${escapeHtml(varName)}.exit_code - ${t('varPreview.exitCode')}
+
${escapeHtml(varName)}.extracted - ${t('varPreview.extracted')}
+
${escapeHtml(varName)}.expect_matched - ${t('varPreview.expectMatched')}
+
${escapeHtml(varName)}.fail_matched - ${t('varPreview.failMatched')}
+
${escapeHtml(varName)}.host - ${t('varPreview.host')}
+
${escapeHtml(varName)}.timestamp - ${t('varPreview.timestamp')}
`; } @@ -20956,7 +21050,7 @@ async function submitAddSource() { const enabled = document.getElementById('source-enabled').checked; if (!id) { - alert(typeof t === 'function' ? t('automation.alertEnterSourceId') : '请输入数据源 ID'); + alert(typeof t === 'function' ? t('ui.alertEnterSourceId') : '请输入数据源 ID'); return; } @@ -20969,7 +21063,7 @@ async function submitAddSource() { params.reconnect_ms = parseInt(document.getElementById('source-ws-reconnect').value) || 5000; if (!params.uri) { - alert(typeof t === 'function' ? t('automation.alertEnterWsUri') : '请输入 WebSocket URI'); + alert(typeof t === 'function' ? t('ui.alertEnterWsUri') : '请输入 WebSocket URI'); return; } } else if (type === 'rest') { @@ -20979,7 +21073,7 @@ async function submitAddSource() { params.auth_header = document.getElementById('source-rest-auth').value.trim(); if (!params.url) { - alert(typeof t === 'function' ? t('automation.alertEnterRestUrl') : '请输入 REST URL'); + alert(typeof t === 'function' ? t('ui.alertEnterRestUrl') : '请输入 REST URL'); return; } } else if (type === 'socketio') { @@ -20994,11 +21088,11 @@ async function submitAddSource() { params.auto_discover = autoDiscoverEl ? autoDiscoverEl.checked : true; if (!params.url) { - alert(typeof t === 'function' ? t('automation.alertEnterSioAddress') : '请输入 Socket.IO 服务器地址'); + alert(typeof t === 'function' ? t('ui.alertEnterSioAddress') : '请输入 Socket.IO 服务器地址'); return; } if (!params.event) { - alert(typeof t === 'function' ? t('automation.alertEnterSioEvent') : '请输入要监听的事件名称(可先通过测试按钮自动发现)'); + alert(typeof t === 'function' ? t('ui.alertEnterSioEvent') : '请输入要监听的事件名称(可先通过测试按钮自动发现)'); return; } } else if (type === 'variable') { @@ -21007,18 +21101,18 @@ async function submitAddSource() { const cmdIdx = document.getElementById('source-ssh-cmd').value; if (!hostId) { - alert(typeof t === 'function' ? t('automation.alertSelectSshHost') : '请选择 SSH 主机'); + alert(typeof t === 'function' ? t('ui.alertSelectSshHost') : '请选择 SSH 主机'); return; } if (cmdIdx === '') { - alert(typeof t === 'function' ? t('automation.alertSelectSshCmd') : '请选择 SSH 指令'); + alert(typeof t === 'function' ? t('ui.alertSelectSshCmd') : '请选择 SSH 指令'); return; } // 获取选中的命令配置 const cmd = sshCommands[hostId]?.[parseInt(cmdIdx)]; if (!cmd) { - alert(typeof t === 'function' ? t('automation.alertCmdNotExist') : '指令不存在,请重新选择'); + alert(typeof t === 'function' ? t('ui.alertCmdNotExist') : '指令不存在,请重新选择'); return; } @@ -21172,6 +21266,11 @@ function showAddRuleModal(ruleData = null) {
+
+ + + +
${typeof t === 'function' ? t('automation.triggerConditions') : '触发条件'} @@ -21216,6 +21315,11 @@ function showAddRuleModal(ruleData = null) { // 如果是编辑模式,填充现有数据 if (isEdit && ruleData) { document.getElementById('rule-id').value = ruleData.id; + document.getElementById('rule-id').disabled = true; + document.getElementById('rule-show-dashboard').checked = ruleData.show_on_dashboard === true; + document.getElementById('rule-show-dashboard').dataset.present = String(Object.hasOwn(ruleData, 'show_on_dashboard')); + document.getElementById('rule-allow-manual').checked = ruleData.allow_manual_trigger === true; + document.getElementById('rule-allow-manual').dataset.present = String(Object.hasOwn(ruleData, 'allow_manual_trigger')); document.getElementById('rule-name').value = ruleData.name || ''; document.getElementById('rule-logic').value = ruleData.logic || 'and'; document.getElementById('rule-cooldown').value = ruleData.cooldown_ms || 0; @@ -21238,7 +21342,7 @@ function showAddRuleModal(ruleData = null) { // 填充条件 if (ruleData.conditions && ruleData.conditions.length > 0) { ruleData.conditions.forEach(cond => { - addConditionRow(cond.variable, cond.operator, cond.value); + addConditionRow(cond.variable, cond.operator, cond.value, cond); }); } @@ -21251,17 +21355,18 @@ function showAddRuleModal(ruleData = null) { // 填充动作 if (ruleData.actions && ruleData.actions.length > 0) { // 异步加载动作模板行 + modal.dataset.loading = 'true'; (async () => { - for (const act of ruleData.actions) { + try { for (const act of ruleData.actions) { await addActionTemplateRow( act.template_id, act.delay_ms || 0, act.repeat_mode || 'once', act.repeat_count || 1, - act.repeat_interval_ms || 1000, - act.condition || null + act.repeat_interval_ms ?? 1000, + act.condition || null, act ); - } + } } finally { modal.dataset.loading = 'false'; } })(); } } @@ -21272,22 +21377,15 @@ function showAddRuleModal(ruleData = null) { */ function toggleManualOnly() { const checked = document.getElementById('rule-manual-only').checked; - const addBtn = document.getElementById('add-condition-btn'); + document.getElementById('add-condition-btn').disabled = checked; const container = document.getElementById('conditions-container'); - - if (checked) { - // 禁用添加条件按钮,清空现有条件 - addBtn.disabled = true; - addBtn.style.opacity = '0.5'; - container.innerHTML = '

' + (typeof t === 'function' ? t('ui.manualTriggerOnly') : '此规则仅可通过手动触发按钮执行') + '

'; - } else { - // 启用添加条件按钮 - addBtn.disabled = false; - addBtn.style.opacity = '1'; - container.innerHTML = '

' + (typeof t === 'function' ? t('automation.addConditionHintShort') : '点击"添加"创建触发条件') + '

'; - } + container.querySelectorAll('input, select, button').forEach(el => { el.disabled = checked; }); + let note = document.getElementById('rule-preserved-conditions'); + if (!note) { note = document.createElement('p'); note.id = 'rule-preserved-conditions'; container.before(note); } + note.textContent = checked ? runtimeText('conditionsPreserved') : ''; } + // ==================== 规则图标选择 ==================== function switchRuleIconType(type) { @@ -21377,7 +21475,7 @@ let conditionRowCount = 0; * @param {string} operator - 预填充操作符 * @param {any} value - 预填充比较值 */ -function addConditionRow(variable = '', operator = 'eq', value = '') { +function addConditionRow(variable = '', operator = 'eq', value = '', original = null) { const container = document.getElementById('conditions-container'); // 移除空提示 @@ -21392,7 +21490,7 @@ function addConditionRow(variable = '', operator = 'eq', value = '') { } // 处理值显示 - let displayValue = value; + let displayValue = typeof value === 'string' ? JSON.stringify(value) : value; if (typeof value === 'object') { displayValue = JSON.stringify(value); } else if (typeof value === 'boolean') { @@ -21402,6 +21500,7 @@ function addConditionRow(variable = '', operator = 'eq', value = '') { const rowId = conditionRowCount; const row = document.createElement('div'); row.className = 'condition-row'; + row._originalCondition = original ? structuredClone(original) : null; row.id = `condition-row-${rowId}`; row.innerHTML = ` `; @@ -21555,8 +21654,8 @@ async function openConditionVarSelector(rowId) { console.error('加载变量列表失败:', e); document.getElementById('variable-select-loading').innerHTML = `
-

加载失败: ${e.message}

- +

${t('common.loadFailed')}: ${escapeHtml(e.message)}

+
`; } @@ -21613,13 +21712,20 @@ async function loadActionTemplatesForRule() { * @param {number} repeatIntervalMs - 重复间隔毫秒 * @param {Object|null} condition - 动作条件配置 {variable, operator, value} */ -async function addActionTemplateRow(templateId = '', delayMs = 0, repeatMode = 'once', repeatCount = 1, repeatIntervalMs = 1000, condition = null) { +async function addActionTemplateRow(templateId = '', delayMs = 0, repeatMode = 'once', repeatCount = 1, repeatIntervalMs = 1000, condition = null, original = null) { const container = document.getElementById('actions-container'); + if (original && !templateId) { + const row = document.createElement('div'); row.className = 'action-row'; + row._originalAction = structuredClone(original); row.dataset.inline = 'true'; + const label = document.createElement('pre'); label.textContent = JSON.stringify(original, null, 2); + row.appendChild(label); container.querySelector('.empty-hint')?.remove(); container.appendChild(row); + return; + } // 先加载模板列表 await loadActionTemplatesForRule(); - if (cachedActionTemplates.length === 0) { + if (cachedActionTemplates.length === 0 && !original) { showToast(typeof t === 'function' ? t('toast.createActionFirst') : '请先创建动作模板', 'warning'); return; } @@ -21630,16 +21736,19 @@ async function addActionTemplateRow(templateId = '', delayMs = 0, repeatMode = ' const row = document.createElement('div'); row.className = 'action-row template-select-row'; + row._originalAction = original ? structuredClone(original) : null; row.id = `action-row-${actionRowCount}`; // 构建模板选项 - let optionsHtml = ''; + let optionsHtml = ''; cachedActionTemplates.forEach(tpl => { const typeLabel = getActionTypeLabel(tpl.type); const selected = tpl.id === templateId ? 'selected' : ''; optionsHtml += ``; }); + if (templateId && !cachedActionTemplates.some(tpl => tpl.id === templateId)) + optionsHtml += ``; const rowId = actionRowCount; const showRepeatOptions = repeatMode !== 'once'; const hasCondition = condition && condition.variable; @@ -21654,25 +21763,25 @@ async function addActionTemplateRow(templateId = '', delayMs = 0, repeatMode = '
@@ -21681,7 +21790,7 @@ async function addActionTemplateRow(templateId = '', delayMs = 0, repeatMode = '
@@ -21719,11 +21829,11 @@ function getActionTypeLabel(type) { 'cli': 'CLI', 'ssh_cmd_ref': 'SSH', 'led': 'LED', - 'log': '日志', - 'set_var': '变量', + 'log': t('common.log'), + 'set_var': t('common.variable'), 'webhook': 'Webhook', 'gpio': 'GPIO', - 'device_ctrl': '设备' + 'device_ctrl': t('common.devices') }; return labels[type] || type; } @@ -21821,21 +21931,21 @@ async function showVariableSelectModalForCondition() {
`; @@ -21919,8 +22029,8 @@ async function showVariableSelectModalForCondition() { console.error('加载变量列表失败:', e); document.getElementById('variable-select-loading').innerHTML = `
-

加载失败: ${e.message}

- +

${t('common.loadFailed')}: ${escapeHtml(e.message)}

+
`; } @@ -21973,7 +22083,7 @@ function updateActionFields(selectElement) { - + `; break; @@ -21981,10 +22091,10 @@ function updateActionFields(selectElement) { paramsContainer.innerHTML = ` - + `; break; case 'device': @@ -21994,17 +22104,17 @@ function updateActionFields(selectElement) { `; break; case 'set_var': paramsContainer.innerHTML = ` - - + + `; break; case 'log': @@ -22014,7 +22124,7 @@ function updateActionFields(selectElement) { - + `; break; case 'webhook': @@ -22037,6 +22147,8 @@ function updateActionFields(selectElement) { * @param {string} originalId - 编辑模式时传入原规则 ID */ async function submitAddRule(originalId = null) { + const modal = document.getElementById('add-rule-modal'); + if (modal?.dataset.saving === 'true' || modal?.dataset.loading === 'true') return; const isEdit = !!originalId; const id = document.getElementById('rule-id').value.trim(); const name = document.getElementById('rule-name').value.trim(); @@ -22057,7 +22169,7 @@ async function submitAddRule(originalId = null) { // 收集条件(仅手动触发时为空数组) const conditions = []; - if (!manualTrigger) { + { document.querySelectorAll('.condition-row').forEach(row => { const variable = row.querySelector('.cond-variable').value.trim(); const operator = row.querySelector('.cond-operator').value; @@ -22071,19 +22183,23 @@ async function submitAddRule(originalId = null) { // 保持字符串 } - conditions.push({ variable, operator, value }); + const condition = { variable, operator, value }; + if (row._originalCondition && Object.is(value, row._originalCondition.value) && row._originalCondition.value_type !== undefined) + condition.value_type = row._originalCondition.value_type; + conditions.push(condition); } }); } // 收集动作模板引用(包含 template_id、delay_ms、重复选项和动作条件) const actions = []; - document.querySelectorAll('.action-row').forEach(row => { + document.querySelectorAll('#add-rule-modal .action-row').forEach(row => { + if (row.dataset.inline === 'true') { actions.push(structuredClone(row._originalAction)); return; } const templateId = row.querySelector('.action-template-id')?.value; const delay_ms = parseInt(row.querySelector('.action-delay')?.value) || 0; const repeat_mode = row.querySelector('.action-repeat-mode')?.value || 'once'; const repeat_count = parseInt(row.querySelector('.action-repeat-count')?.value) || 1; - const repeat_interval_ms = parseInt(row.querySelector('.action-repeat-interval')?.value) || 1000; + const repeat_interval_ms = Number(row.querySelector('.action-repeat-interval')?.value ?? 1000); // 收集动作条件 const hasCondition = row.querySelector('.action-has-condition')?.checked; @@ -22092,10 +22208,13 @@ async function submitAddRule(originalId = null) { const condValueRaw = row.querySelector('.action-condition-value')?.value?.trim(); if (templateId) { - const actionRef = { - template_id: templateId, - delay_ms: delay_ms - }; + const actionRef = row._originalAction?.template_id === templateId ? structuredClone(row._originalAction) : {}; + actionRef.template_id = templateId; + actionRef.delay_ms = delay_ms; + actionRef.repeat_mode = repeat_mode; + actionRef.repeat_count = repeat_count; + actionRef.repeat_interval_ms = repeat_interval_ms; + delete actionRef.condition; // 只有非单次执行时才添加重复参数 if (repeat_mode !== 'once') { @@ -22121,6 +22240,9 @@ async function submitAddRule(originalId = null) { operator: condOperator, value: condValue }; + const oldCondition = row._originalAction?.condition; + if (oldCondition && Object.is(oldCondition.value, condValue) && oldCondition.value_type !== undefined) + actionRef.condition.value_type = oldCondition.value_type; } actions.push(actionRef); @@ -22128,7 +22250,7 @@ async function submitAddRule(originalId = null) { }); if (actions.length === 0) { - alert(typeof t === 'function' ? t('automation.alertSelectAction') : '请至少选择一个动作模板'); + alert(typeof t === 'function' ? t('ui.alertSelectAction') : '请至少选择一个动作模板'); return; } @@ -22140,27 +22262,37 @@ async function submitAddRule(originalId = null) { cooldown_ms: cooldown, enabled, manual_trigger: manualTrigger, + show_on_dashboard: document.getElementById('rule-show-dashboard').checked, + allow_manual_trigger: document.getElementById('rule-allow-manual').checked, + expected_revision: Number(document.getElementById('rule-revision').value), conditions, actions }; - try { - // 编辑模式:先删除旧规则,再创建新规则 - if (isEdit) { - await api.call('automation.rules.delete', { id: originalId }); + if (isEdit) { + for (const [element, field] of [['rule-show-dashboard', 'show_on_dashboard'], ['rule-allow-manual', 'allow_manual_trigger']]) { + const input = document.getElementById(element); + if (input.dataset.present === 'false' && input.dataset.dirty !== 'true') delete params[field]; } - - const result = await api.call('automation.rules.add', params); + } + modal.dataset.saving = 'true'; + try { + const result = await api.call(isEdit ? 'automation.rules.update' : 'automation.rules.add', params); if (result.code === 0) { - showToast(typeof t === 'function' ? t('toast.ruleCreated', { id, action: isEdit ? t('toast.ruleUpdate') : t('toast.ruleCreate') }) : `规则 ${id} ${isEdit ? '更新' : '创建'}成功`, 'success'); + showToast(runtimeText(result.data?.mirror_synced === false ? 'mirrorWarning' : 'saved'), result.data?.mirror_synced === false ? 'warning' : 'success'); closeModal('add-rule-modal'); await Promise.all([refreshRules(), refreshAutomationStatus()]); } else { - showToast(typeof t === 'function' ? t('toast.ruleCreateFailed', { action: isEdit ? t('toast.ruleUpdate') : t('toast.ruleCreate') }) + ': ' + result.message : `${isEdit ? '更新' : '创建'}规则失败: ${result.message}`, 'error'); + showToast(runtimeSaveError(result), 'error'); } } catch (error) { - showToast(typeof t === 'function' ? t('toast.ruleCreateFailed', { action: isEdit ? t('toast.ruleUpdate') : t('toast.ruleCreate') }) + ': ' + error.message : `${isEdit ? '更新' : '创建'}规则失败: ${error.message}`, 'error'); - } + showToast(runtimeText('saveUnknown'), 'warning'); + // Re-read once, never replay the write. Keep the editor and its draft. + try { + const current = await api.call('automation.rules.get', { id }); + if (current.code === 0) document.getElementById('rule-revision').dataset.observedRevision = current.data.revision; + } catch (_) { /* Remain explicitly uncertain. */ } + } finally { modal.dataset.saving = 'false'; } } /** @@ -22442,7 +22574,7 @@ async function previewSourceImport() { importBtn.disabled = false; } else { resultBox.className = 'result-box error'; - resultBox.textContent = (result.message || '无法验证配置包'); + resultBox.textContent = (result.message || t('ssh.cannotVerifyPack')); } } catch (e) { resultBox.className = 'result-box error'; @@ -22553,10 +22685,10 @@ async function doExportRule(ruleId) { if (certText) params.recipient_cert = certText; const result = await api.call('automation.rules.export', params); - if (result.code !== 0) throw new Error(result.message || '导出失败'); + if (result.code !== 0) throw new Error(result.message || t('toast.exportFailed')); const data = result.data; - if (!data?.tscfg) throw new Error('无效的响应数据'); + if (!data?.tscfg) throw new Error(t('toast.invalidResponse')); // 下载文件 const blob = new Blob([data.tscfg], { type: 'application/json' }); @@ -22962,7 +23094,7 @@ async function previewActionImport() { importBtn.disabled = false; } else { resultBox.className = 'result-box error'; - resultBox.textContent = (result.message || '无法验证配置包'); + resultBox.textContent = (result.message || t('ssh.cannotVerifyPack')); } } catch (e) { resultBox.className = 'result-box error'; diff --git a/components/ts_webui/web/js/lang/en-US.js b/components/ts_webui/web/js/lang/en-US.js index 6d16946..cae057d 100644 --- a/components/ts_webui/web/js/lang/en-US.js +++ b/components/ts_webui/web/js/lang/en-US.js @@ -2,6 +2,261 @@ * TianShanOS WebUI - English Language Pack */ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { + promptRepair: { + taskResults: 'Configuration task history', + taskAttempt: 'Attempt {attempt}: {path}', + retry: 'Retry', + pageLoadFailed: 'The page could not be loaded. Please retry.', + logoutConfirmed: "Signed out locally. The server acknowledged the sign-out request.", + logoutLocal: "Local sign-in information was cleared. The server session has not been confirmed as ended.", + packRevalidate: "This package verification is no longer current. Upload and verify it again.", + listRefreshFailed: "The file list could not be refreshed. Refresh it manually. Confirmed upload results are unchanged.", + + "phase_PLATFORM": "Platform initialization", + "phase_CORE": "Core services", + "phase_HAL": "Hardware access", + "phase_DRIVER": "Device drivers", + "phase_NETWORK": "Network services", + "phase_SECURITY": "Security services", + "phase_SERVICE": "Application services", + "phase_UI": "User interface", + + "forceOff": "Force power off", + "state_UNREGISTERED": "Not registered", + "state_REGISTERED": "Registered", + "state_STARTING": "Starting", + "state_RUNNING": "Running", + "state_STOPPING": "Stopping", + "state_STOPPED": "Stopped", + "state_ERROR": "Error", + "state_Running": "Running", + "state_Ready": "Ready to run", + "state_Blocked": "Waiting for a resource or event", + "state_Suspended": "Suspended", + "state_Deleted": "Deleted", + + "settingsTitle": "{device} · Settings", + "viewVariables": "View variables: {name}.*", + "ledServiceStatus": "Check LED service status", + "customColor": "Custom color", + "organization": "Organization", + "wwwPartial": "Firmware was written, but the WebUI upgrade failed; no restart was requested.", + "wwwRetry": "Retry WebUI upgrade", + "variableCount": "{count} variables", + "variableExample": "Example: system.flag", + "valueExample": "Examples: true, 123, ${other_var}", + "webhookConfig": "Webhook settings", + "qrVariableHint": "Text or URL; supports ${variable_name}", + "noHosts": "No hosts available. Add a host on the SSH page first.", + "noCommands": "This host has no commands. Add one on the SSH page first.", + "chooseCommand": "Select a command", + "chooseAction": "Select an action template", + "unknownFilter": "Unknown filter", + "colorRed": "Red", + "colorOrange": "Orange", + "colorYellow": "Yellow", + "colorGreen": "Green", + "colorCyan": "Cyan", + "colorBlue": "Blue", + "colorPurple": "Purple", + "colorWhite": "White", + "colorPink": "Pink", + "colorGray": "Gray", + "filterFadeIn": "Fade in", + "filterFadeOut": "Fade out", + "filterColorShift": "Color shift", + + "keyVerified": "Key “{id}” was deployed to {target}; public-key sign-in was verified.", + "keyUnverified": "Key “{id}” was deployed to {target}, but public-key sign-in is unconfirmed.", + "packApplied": "The configuration package was applied.", + "filesSelected": "{count} files selected", + "fileErrors": "{count} files could not be read: {message}", + "packGenerated": "Configuration package generated\nFile: {name}\nSize: {size} bytes; contains {count} configuration files", + "orphanCount": "The hosts referenced by {count} commands no longer exist", + "orphanHost": "Host “{id}” does not exist. Select another host for this command or delete the command.", + "expectedLabel": "Expected output:", + "failureLabel": "Failure condition:", + "extractLabel": "Extraction rule:", + "servicePattern": "Service readiness condition: {pattern}", + "waitEvent": "Connecting and waiting for event: {event}", + "event": "Event", + "noEvent": "A session was established, but no event data was received.", + "outputPreview": "Output: {output}", + "upgradeWritten": "Upgrade files were written. Requesting a device restart.", + "rebootUnknown": "Restart confirmation was not received. The device may be restarting; wait for the status check before repeating the operation.", + "horizontal": "Horizontal", + "vertical": "Vertical", + "diagonalRight": "Diagonal ↘", + "diagonalLeft": "Diagonal ↙", + "effect_rainbow": "Rainbow", + "effect_breathing": "Breathing", + "effect_solid": "Solid color", + "effect_sparkle": "Sparkle", + "effect_pulse": "Pulse", + "effect_color_cycle": "Color cycle", + "effect_heartbeat": "Heartbeat", + "effect_chase": "Chase", + "effect_comet": "Comet", + "effect_spin": "Spin", + "effect_breathe_wave": "Breathing wave", + "effect_fire": "Fire", + "effect_rain": "Rain", + "effect_coderain": "Code rain", + "effect_plasma": "Plasma", + "effect_ripple": "Ripple", + "effect_unknown": "Unknown animation", + + "sshAccepted": "The device accepted the execution request. Process startup and readiness are not yet confirmed.\n\n", + "sshCheckOutput": "Use the buttons above to check logs or process status.\n", + "sshBegin": "--- Execution started ---\n", + "sshEnd": "\n--- Execution ended ---\n", + "sshCancelOutput": "\nCancellation handling finished; remote command termination is not confirmed.\n", + "noOutput": "(No output)\n", + "serviceStoppedOutput": "The service has stopped.\n", + "processStoppedOutput": "The process has stopped.\n", + "tailStopped": "\nLive log tracking stopped.\n", + "matchSettings": "\nOutput matching settings:\n", + "stopOnMatch": " Stop after a match: yes\n", + "modeFailed": "The fan mode could not be changed.", + "noResponse": "No response data was received.", + "enterOtaPath": "Enter the path to the firmware file or its folder.", + "otaPathFailed": "The SD card upgrade file could not be read. Check its path.", + "wwwSibling": "Check that www.bin is in the same folder as the firmware file.", + "startFailed": "The operation could not be started.", + "webUploadFailed": "The WebUI file could not be uploaded.", + "firmwareDownloading": "Downloading firmware…", + "firmwareStep": "[1/2] Firmware ", + "webUpgradeFailed": "WebUI upgrade incomplete: ", + "hiddenPrefix": "[Hidden] ", + "officialSuffix": " (Official)", + "logFile": "Log file: {path}\n", + "logFileSpaced": "\nLog file: {path}\n", + "processKeyword": "Process keyword: {keyword}\n", + "sessionWaiting": "Session ID: {id}\nWaiting for output…\n\n", + "expectedPattern": " Expected output pattern: {pattern}\n", + "failurePattern": " Failure output pattern: {pattern}\n", + "extractPattern": " Extraction pattern: {pattern}\n", + "storedVariable": " Store in variable: {name}.*\n", + "exitCode": "Exit code: {code}\n", + "extractedLine": "Extracted content: {value}\n", + "extractedBlock": "\nExtracted content:\n{value}\n", + "sshError": "\nExecution error: {message}\n", + "executionFailed": "Execution did not complete: {message}\n", + "stopFailed": "The service could not be confirmed stopped: {message}", + "firmwareMissing": "Firmware file not found: {path}", + "wwwMissing": "WebUI file not found: {path}", + "directoryUnreadable": "Folder could not be read: {path}", + "firmwareDirMissing": "No firmware .bin file was found in: {path}", + "wwwDirMissing": "WebUI file not found: {path}/www.bin", + "dnsFailed": "The device could not resolve the server address: {host}", + "tcpFailed": "The device could not connect to the server: {host}:{port}", + "httpFailed": "The device could not retrieve content from the server: {message}", + "httpStatus": "The server returned an error (HTTP {status}).", + "downloadHttpStatus": "Download failed (HTTP {status}).", + "sshStopping": "The process is still running. Requesting forced termination…\n", + "stopUnconfirmed": "Forced termination was requested, but the process state is unconfirmed. Check its status.", + "credentials": "The username or password is incorrect.", + "oldPassword": "The current password is incorrect. Enter it again.", + "sdUnavailable": "The SD card is not available. Check that it is inserted and mounted.", + "sdMounted": "The SD card is already mounted.", + "fileMissing": "This file could not be found. Refresh the file list.", + "directoryMissing": "This folder could not be found. Refresh the file list.", + "rootDirectory": "The storage root cannot be deleted. Select a file or folder inside it.", + "fileInfo": "File information could not be read. Check the storage device and refresh the list.", + "unknownError": "The operation could not be completed. See the details below.", + "invalidInput": "The submitted information is not valid. Check the relevant settings.", + "notFound": "The requested item could not be found. Refresh the list to check whether it still exists.", + "permission": "Your account does not have permission to perform this operation.", + "busy": "The device is busy. Wait for the current operation to finish.", + "timeout": "A complete response was not received in time. The result is unconfirmed; check the current state first.", + "resultUnknown": "No complete confirmation was received. The result is unknown. Check the current state before repeating the operation.", + "memory": "The device does not have enough available memory to complete the operation.", + "internal": "The device encountered an error while processing the request. See the details below.", + "unsupported": "This operation is not supported by this device.", + "hardware": "The hardware operation could not be completed. Check the relevant hardware status.", + "connection": "The device or target service could not be reached. Check the network connection.", + "auth": "Authentication failed. Check your credentials or sign in again.", + "invalidResponse": "The device response could not be read. The result is unconfirmed.", + "details": "Details: {detail}", + "deleteSummary": "Deletion results: {success} succeeded; {fail} failed or are unconfirmed.", + "downloadSummary": "Downloads requested in the browser: {success}; not started: {fail}. Check the browser for saved files.", + "uploadSummary": "Upload results: {success} uploaded; {fail} failed or unconfirmed; {invalid} configuration packages failed verification. Uploading does not apply a configuration.", + "ledSummary": "Lights switched off: {success}; failed or unconfirmed: {fail}.", + "uploaded": "The file has been uploaded.", + "packVerified": "Uploaded and signature verified; not yet applied.", + "packInvalid": "The file was uploaded, but package verification failed. It cannot be applied.", + "downloadStarted": "The download has been requested in the browser. Check the browser for the saved file.", + "hiddenNetwork": "Hidden network", + "wifiPassword": "Enter the password for “{ssid}”; leave it blank for an open network:", + "logConnected": "Live log connection established", + "logDisconnected": "Live logs disconnected; waiting to reconnect", + "sshSubmissionUnknown": "Command acceptance was not confirmed. Check the logs or process status before submitting it again.", + "sshDiagnostics": "Reported status: {status}; exit code: {code}", + "sshUnknown": "The command result is unconfirmed. Check the output and status details.", + "sshTimeout": "The command timed out. Check the output to see what was executed.", + "sshCancelled": "Cancellation handling finished; remote command termination is not confirmed.", + "sshFailureOutput": "The output matched a configured failure condition. Check the command output.", + "sshExpectedMissing": "The command ended without the expected output.", + "sshExpectedFound": "The expected output was detected. Waiting for the final result.", + "sshFailed": "The command failed. Check its output and exit code.", + "sshSuccess": "The command completed successfully.", + "lpmuProbeFailed": "The LPMU network check failed. Its power state is unknown.", + "lpmuReachable": "LPMU is reachable over the network. This check does not confirm its power state.", + "lpmuUnreachable": "LPMU is unreachable over the network. This does not confirm that it is powered off.", + "retry": "Retry", + "terminalLoadFailed": "Terminal components could not be loaded. Check the network and retry.", + "terminalRestoring": "Restoring the terminal session. Waiting for connection confirmation.", + "terminalRestored": "The terminal session has been restored. Previous commands were not resent.", + "terminalRestoreTimeout": "Terminal session recovery timed out. Connection is unconfirmed.", + "terminalRestoreFailed": "The terminal session could not be restored. Reconnect to continue.", + "noInitialColor": "No initial color configuration is available to restore.", + "serviceStarted": "Service “{name}” started successfully.", + "serviceStopped": "Service “{name}” stopped successfully.", + "serviceRestarted": "Service “{name}” restarted successfully.", + "ruleCreated": "Rule “{id}” created successfully.", + "ruleUpdated": "Rule “{id}” updated successfully." +}, + + runtimeRepair: { + configLoading: 'Configuration is loading. Refresh shortly.', + confirmFingerprint: 'Verify this server fingerprint through a trusted channel. Trust this exact fingerprint and connect?', + saved: 'Saved', + "showDashboard": "Show on dashboard", + "allowManual": "Allow manual execution", + "conditionsPreserved": "Manual mode preserves conditions; automatic evaluation resumes on the next cycle.", + "saveFailed": "Save failed; draft retained", + "saveUnknown": "Save outcome unknown. Read back before resubmitting.", + "mirrorWarning": "Saved, but backup is not synchronized. Keep the SD card installed.", + "revision_conflict": "Configuration changed. Reload and merge your draft.", + "source_read_only": "This configuration source is read-only; original retained.", + "recovery_required": "Configuration recovery is required; automatic execution paused.", + "commit_unknown": "Save outcome unknown; recovery required.", + "execution_busy": "Rule is executing; operation unavailable.", + "service_busy": "Service is active or unconfirmed. Verify and stop it first.", + "busy_retired_config": "Previous configuration is still in use; retry later.", + "disabled": "Disabled", + "manual": "Manual", + "automatic": "Automatic", + "referenceUnresolved": "Unresolved reference", + "unknown": "Unconfirmed", + "running": "Process running", + "ready": "Readiness log matched", + "checking": "Checking readiness log", + "starting": "Starting", + "stopping": "Stopping", + "stopped": "Process confirmed stopped", + "failed": "Failure log matched", + "timeout": "Readiness check timed out", + "lastKnown": "Last known", + "confirmedAt": "Last confirmation (uptime)", + "stateEvidence": "Evidence source", + "startBlocked": "Start unavailable: check enablement, manual permission and service state.", + "outcomeUnknown": "Remote outcome unknown; it may still be running. Verify before retrying.", + "confirmStop": "Stop the remote service?", + "confirmStopAutomatic": "Stop the remote service? An enabled automatic rule may start it on the next matching evaluation. Disable the rule to keep it stopped.", + "refresh_required": "Refresh this outdated page before editing." +}, + // Common common: { confirm: 'Confirm', @@ -257,7 +512,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { lpmu: 'LPMU', agxRunning: 'AGX Running', agxStopped: 'AGX Stopped', - lpmuDetecting: 'LPMU Detecting', + lpmuDetecting: "Check result unknown", usbMux: 'USB Switch', widgetManager: 'Widget Manager', @@ -307,21 +562,21 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { agxPowerOnSuccess: 'AGX powered on', agxPowerOffSuccess: 'AGX powered off', agxPowerFail: 'AGX operation failed', - lpmuRunning: 'LPMU Running', - lpmuStopped: 'LPMU Stopped', - lpmuOnlineTitle: 'LPMU online (ping 10.10.99.99 reachable)\nClick to trigger power button', - lpmuOfflineTitle: 'LPMU offline (ping 10.10.99.99 unreachable)\nClick to trigger power button', + lpmuRunning: "Network reachable", + lpmuStopped: "Network unreachable", + lpmuOnlineTitle: "LPMU is reachable over the network. This check does not confirm its power state.", + lpmuOfflineTitle: "LPMU is unreachable over the network. This does not confirm that it is powered off.", lpmuDetectingTitle: 'Detecting LPMU status...\nWait up to 80 seconds', - lpmuUnknownTitle: 'LPMU status unknown\nClick to trigger power button', + lpmuUnknownTitle: "The LPMU network check failed. Its power state is unknown.", statusFetching: 'Fetching status', lpmuTriggerConfirm: 'Trigger LPMU power button?\n\nThis sends a pulse, like pressing the physical power button.', lpmuTriggering: 'LPMU power trigger...', lpmuTriggerSuccess: 'LPMU trigger sent, detecting status...', lpmuTriggerFail: 'LPMU trigger failed', - lpmuOnlineSuccess: 'LPMU is online', - lpmuOfflineSuccess: 'LPMU is off', - lpmuStartupTimeout: 'LPMU startup detection timeout, assumed off', - lpmuShutdownTimeout: 'LPMU shutdown timeout, device may still be running' + lpmuOnlineSuccess: "LPMU is reachable over the network. This check does not confirm its power state.", + lpmuOfflineSuccess: "LPMU is unreachable over the network. This does not confirm that it is powered off.", + lpmuStartupTimeout: "LPMU is unreachable over the network. This does not confirm that it is powered off.", + lpmuShutdownTimeout: "LPMU is reachable over the network. This check does not confirm its power state." }, // Fan Control @@ -506,6 +761,14 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { // SSH Commands ssh: { + restartToTakeEffect: "Restart the system to apply the changes.", + note: "Notes", + useConfigHost: "Use the host from the configuration", + includeHostConfigHint: "Include this to import the complete configuration on the target device.", + serviceModeVarHint: "Service status is stored in ${变量名}.status (ready/checking/timeout).", + timeoutConditionHint: "The timeout applies only when a success or failure pattern is set, or “Stop on match” is enabled.", + matchTimeoutHint: "The command will be terminated when the matching timeout is reached.", + hostNotExistCannotExec: "This host no longer exists. Select another host before running the command.", title: 'SSH Commands', hosts: 'Hosts', commands: 'Commands', @@ -719,6 +982,20 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { // Automation automation: { + displayQrCode: "Display QR code", + displayImage: "Display image", + programEffect: "Animation", + solidFill: "Solid color", + selectLedDeviceHint: "Select the LED device to control.", + ledConfig: "LED control settings", + variableLabel: "Variable:", + sshCmdHint: "Select a command configured on the SSH management page.", + sshCmdConfig: "SSH command settings", + resultVariableHint: "Store command output in this variable.", + fan: "Fan", + agxRestart: "Restart AGX", + cliPlaceholder: "e.g.: gpio --set 48 1", + cliConfig: "Console command settings", title: 'Automation Engine', status: 'Engine Status', sources: 'Data Sources', @@ -783,7 +1060,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { importRuleTitle: 'Import Rule Config', importRuleDesc: 'Select .tscfg config file to import rule', exportActionTitle: 'Export Action Template', - exportActionDesc: 'Export action {id} config as encrypted package', + exportActionDesc: 'Export the configuration for action {actionId} as an encrypted package', importActionTitle: 'Import Action Template', importActionDesc: 'Select .tscfg config file to import action template', packTypeSource: 'Data source', @@ -1116,7 +1393,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { configRestartRequired: 'Takes effect after restart', verifySuccess: 'Verification passed', importSuccess: 'Import successful', - keyGenerated: 'Key generated', + keyGenerated: 'Key “{name}” generated successfully.', keyDeployed: 'Key deployed', confirmTrigger: 'Confirm trigger?', triggerSuccess: 'Trigger successful', @@ -1142,7 +1419,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { serviceSuccess: 'Service {name} {action} successful', // Voltage protection voltageProtectionEnabled: 'Voltage protection enabled', - lowVoltageWarning: 'Low voltage warning: {voltage}V ({countdown}s)', + lowVoltageWarning: "Input voltage is low: {voltage} V. Shutdown countdown: {countdown} seconds.", voltageProtectionTriggered: 'Voltage protection triggered', voltageRecovering: 'Voltage recovering: {voltage}V', voltageProtectionDisabled: 'Voltage protection disabled', @@ -1172,7 +1449,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { firmwareWriteComplete: 'Firmware write complete!', webuiWriteComplete: 'WebUI write complete!', webuiUpgradeSkipped: 'WebUI upgrade skipped: {msg}', - nohupStripped: 'Auto-removed redundant nohup wrapper (backend adds it)', + nohupStripped: "Duplicate background execution parameters were removed. The system will run this command in the background.", saveCommandFailedMsg: 'Failed to save command: {msg}', deleteCommandFailedMsg: 'Failed to delete command: {msg}', fillServerInfo: 'Please fill in complete server information', @@ -1434,12 +1711,12 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { commandSuccess: 'Command executed successfully', commandMatchFailed: 'Command completed, pattern match failed', commandTimeout: 'Command execution timeout', - commandCompletedCode: 'Command completed, exit code: {code}', + commandCompletedCode: "The command did not complete successfully (exit code: {code}). Check its output.", execError: 'Execution error', execErrorMsg: 'Execution error: {msg}', - commandCancelled: 'Command cancelled', + commandCancelled: 'Cancellation handled; remote outcome unconfirmed', hostFingerprintDeleted: 'Host fingerprint deleted', - hostInfoEmpty: 'Host information is empty', + hostInfoEmpty: "No connection settings are available for this host. Check its settings.", testingConnection: 'Testing connection to {host}...', cannotGetHostInfo: 'Cannot get host information', connectionSuccess: 'Connection to {host} successful!', @@ -1482,9 +1759,9 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { device: { agxRunning: 'AGX Running', agxStopped: 'AGX Stopped', - lpmuRunning: 'LPMU Running', - lpmuStopped: 'LPMU Stopped', - lpmuDetecting: 'Detecting Status', + lpmuRunning: "Network reachable", + lpmuStopped: "Network unreachable", + lpmuDetecting: "Check result unknown", lpmuUnknown: 'LPMU Status Unknown', lpmuOnlineHint: 'LPMU online (ping 10.10.99.99 reachable)\nClick to trigger power button', lpmuOfflineHint: 'LPMU offline (ping 10.10.99.99 unreachable)\nClick to trigger power button', @@ -1810,8 +2087,8 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { patternMatchSuccess: 'Pattern Match Success!', expectPatternMatch: 'Expect pattern matched: Yes', failPatternMatch: 'Fail pattern matched: Yes', - failMatchedTrue: 'true (error detected)', - failMatchedFalse: 'false', + failMatchedTrue: "A failure condition was detected", + failMatchedFalse: "No failure condition was detected", extractedContent: 'Extracted Content', cancelledExecution: 'Execution cancelled', error: 'Error', @@ -2813,8 +3090,8 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { unbindSuccess: 'Temperature variable unbound', unbindFailed: 'Unbind failed', dutyOrderError: 'Min duty cannot be greater than max duty', - hysteresisRangeError: 'Temperature hysteresis must be 0-20°C', - intervalRangeError: 'Min interval must be 500-30000 ms', + hysteresisRangeError: "The temperature change required to adjust fan speed (hysteresis) must be 0–20°C.", + intervalRangeError: "The minimum time between fan speed adjustments must be 0.5–30 seconds.", curveApplied: 'Fan {id} curve applied and saved', applyCurveFailed: 'Apply curve failed', curveExported: 'Fan {id} curve exported (local + SD {path})', @@ -3137,6 +3414,45 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { }, // PKI/Security Config + pkiRepair: { + "unknown": "Unknown / unconfirmed", + "none": "No device certificate", + "invalid": "Certificate cannot be parsed", + "time_unverified": "Validity: awaiting device time", + "not_yet_valid": "Validity: not yet valid", + "valid": "Within validity period", + "expired": "Validity: expired", + "stored": "Saved", + "missing": "Missing", + "key": "Private key", + "certificate": "Device certificate", + "clientCa": "Client verification CA", + "running": "Running", + "stopped": "Not running", + "restart": "Stored materials changed. The running service still uses the previous materials. Restart the device to apply; startup conditions must be met. Deleting stored credentials does not revoke the active instance.", + "activeFingerprint": "Active certificate SHA-256", + "deviceTime": "Device time", + "synced": "Synchronized", + "unsynced": "Not synchronized", + "timeUnknown": "Device time unavailable; retry refresh", + "syncBrowser": "Set device time from this computer (browser source)", + "empty": "Provide PEM text", + "saved": "Saved. Check validity and actual HTTPS status.", + "unconfirmed": "Installation result unconfirmed. Refresh status to check before retrying.", + "lessDay": "Expires in less than a day", + "expiredLessDay": "Expired less than a day ago", + "block_time_not_ready": "Device time not ready", + "block_private_key_missing": "Private key missing", + "block_private_key_invalid": "Private key invalid", + "block_certificate_missing": "Certificate missing", + "block_certificate_invalid": "Certificate invalid", + "block_key_mismatch": "Key mismatch", + "block_not_yet_valid": "Not yet valid", + "block_expired": "Expired", + "block_ca_missing": "Client verification CA missing", + "block_ca_invalid": "Client verification CA invalid", + "block_storage_error": "Storage uncertain; restart and check materials" +}, pkiPage: { signatureVerified: 'Signature verified', configImported: 'Config package imported', @@ -3193,6 +3509,10 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { // UI Dynamic Text ui: { + confirmDeleteRule: "Delete rule “{id}”? This cannot be undone.", + confirmDeleteSource: "Delete data source “{id}”? This cannot be undone.", + confirmDeleteAction: "Delete action template “{id}”?", + confirmDeleteFiles: "Delete the selected {count} files or folders? This cannot be undone.", // Language chinese: '中文', english: 'EN', @@ -3379,6 +3699,25 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { // Terminal Page terminal: { + sshCapacity: "The result channel is busy. SSH was not started; try again shortly.", + sshCreateFailed: "The SSH session could not be created. Try again shortly.", + sshOpenFailed: "The remote shell could not be opened. Check whether the server permits interactive sessions.", + sshStartupClosed: "The SSH session ended during startup. Check the server before reconnecting.", + sshStatusFailed: "SSH status notification failed. The connection state is unconfirmed; reconnect to check.", + sshOutputIncomplete: "SSH output in this page is incomplete. The remote result is unconfirmed. Check the server before repeating commands.", + sshClosed: "The SSH session has ended.", + sshClosing: "Closing the SSH session; waiting for confirmation.", + sshConnecting: "Establishing the SSH connection…", + sshReady: "The SSH shell is ready.", + sshServiceStopping: "The service is stopping. This request was not accepted.", + sshControlUnsupported: "Unsupported SSH signal; the session is still active.", + sshControlInvalid: "Invalid SSH control parameters; the session is still active.", + sshControlFailed: "This SSH request failed. Input was not replayed.", + sshChannelUnknown: "The SSH channel ended unexpectedly. The remote result is unconfirmed.", + sshWrongOwner: "This connection does not own an active SSH session.", + sshBusy: "Another SSH session is active. This connection attempt was rejected.", + sshRequestRejected: "This SSH request was rejected.", + connecting: 'Connecting to device...', connected: 'Connected to device', helpHint: 'Enter {help} to view available commands', diff --git a/components/ts_webui/web/js/lang/zh-CN.js b/components/ts_webui/web/js/lang/zh-CN.js index d9025ac..1e2f124 100644 --- a/components/ts_webui/web/js/lang/zh-CN.js +++ b/components/ts_webui/web/js/lang/zh-CN.js @@ -2,6 +2,261 @@ * TianShanOS WebUI - 简体中文语言包 */ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { + promptRepair: { + taskResults: '配置应用任务记录', + taskAttempt: '第 {attempt} 次:{path}', + retry: '重试', + pageLoadFailed: '页面加载失败,请重试。', + logoutConfirmed: "已在本地退出,服务端已响应退出请求。", + logoutLocal: "已清除本地登录信息,尚未确认服务端会话已结束。", + packRevalidate: "此配置包的验证结果已失效,请重新上传并验证。", + listRefreshFailed: "文件列表刷新失败,请手动刷新。已确认的上传结果不受影响。", + + "phase_PLATFORM": "平台初始化", + "phase_CORE": "核心服务", + "phase_HAL": "硬件访问层", + "phase_DRIVER": "设备驱动", + "phase_NETWORK": "网络服务", + "phase_SECURITY": "安全服务", + "phase_SERVICE": "应用服务", + "phase_UI": "用户界面", + + "forceOff": "强制关机", + "state_UNREGISTERED": "未注册", + "state_REGISTERED": "已注册", + "state_STARTING": "启动中", + "state_RUNNING": "运行中", + "state_STOPPING": "停止中", + "state_STOPPED": "已停止", + "state_ERROR": "发生错误", + "state_Running": "正在执行", + "state_Ready": "等待调度", + "state_Blocked": "等待资源或事件", + "state_Suspended": "已挂起", + "state_Deleted": "已删除", + + "settingsTitle": "{device} · 设置", + "viewVariables": "查看变量:{name}.*", + "ledServiceStatus": "检查 LED 服务状态", + "customColor": "自定义颜色", + "organization": "组织", + "wwwPartial": "固件已写入,但 WebUI 升级失败;尚未请求重启。", + "wwwRetry": "重试 WebUI 升级", + "variableCount": "{count} 个变量", + "variableExample": "例如:system.flag", + "valueExample": "例如:true、123、${other_var}", + "webhookConfig": "Webhook 配置", + "qrVariableHint": "文本或网址,支持 ${变量名}", + "noHosts": "暂无主机,请先在 SSH 页面添加。", + "noCommands": "该主机暂无命令,请在 SSH 页面添加。", + "chooseCommand": "请选择命令", + "chooseAction": "请选择动作模板", + "unknownFilter": "未知滤镜", + "colorRed": "红", + "colorOrange": "橙", + "colorYellow": "黄", + "colorGreen": "绿", + "colorCyan": "青", + "colorBlue": "蓝", + "colorPurple": "紫", + "colorWhite": "白", + "colorPink": "粉红", + "colorGray": "灰", + "filterFadeIn": "淡入", + "filterFadeOut": "淡出", + "filterColorShift": "色彩偏移", + + "keyVerified": "密钥“{id}”已部署到 {target},并已验证可使用公钥登录。", + "keyUnverified": "密钥“{id}”已部署到 {target},但尚未确认能否使用公钥登录。", + "packApplied": "配置包已应用。", + "filesSelected": "已选择 {count} 个文件", + "fileErrors": "{count} 个文件读取失败:{message}", + "packGenerated": "配置包已生成\n文件:{name}\n大小:{size} 字节;包含 {count} 个配置文件", + "orphanCount": "{count} 个命令关联的主机已不存在", + "orphanHost": "主机“{id}”不存在,请为命令重新选择主机或删除命令。", + "expectedLabel": "预期输出:", + "failureLabel": "失败条件:", + "extractLabel": "提取规则:", + "servicePattern": "服务就绪条件:{pattern}", + "waitEvent": "正在连接,等待事件:{event}", + "event": "事件", + "noEvent": "已建立会话,但未收到事件数据。", + "outputPreview": "输出:{output}", + "upgradeWritten": "升级文件已写入,正在请求设备重启。", + "rebootUnknown": "未收到重启确认。设备可能正在重启,请等待状态检查,不要重复操作。", + "horizontal": "横向", + "vertical": "纵向", + "diagonalRight": "对角 ↘", + "diagonalLeft": "对角 ↙", + "effect_rainbow": "彩虹", + "effect_breathing": "呼吸", + "effect_solid": "纯色", + "effect_sparkle": "闪烁", + "effect_pulse": "脉冲", + "effect_color_cycle": "颜色循环", + "effect_heartbeat": "心跳", + "effect_chase": "追逐", + "effect_comet": "彗星", + "effect_spin": "旋转", + "effect_breathe_wave": "呼吸波", + "effect_fire": "火焰", + "effect_rain": "雨滴", + "effect_coderain": "代码雨", + "effect_plasma": "等离子", + "effect_ripple": "涟漪", + "effect_unknown": "未知动画", + + "sshAccepted": "设备已受理执行请求,进程启动与就绪状态尚待确认。\n\n", + "sshCheckOutput": "请使用上方按钮查看日志或进程状态。\n", + "sshBegin": "--- 开始执行 ---\n", + "sshEnd": "\n--- 执行结束 ---\n", + "sshCancelOutput": "\n取消处理已结束;远端命令是否终止尚未确认。\n", + "noOutput": "(无输出)\n", + "serviceStoppedOutput": "服务已停止。\n", + "processStoppedOutput": "进程已停止。\n", + "tailStopped": "\n已停止实时跟踪。\n", + "matchSettings": "\n输出匹配设置:\n", + "stopOnMatch": " 检测到匹配后停止:是\n", + "modeFailed": "未能切换风扇模式。", + "noResponse": "未收到响应数据。", + "enterOtaPath": "请输入固件文件或所在目录的路径。", + "otaPathFailed": "无法读取 SD 卡升级文件,请检查文件路径。", + "wwwSibling": "请确认 www.bin 与固件文件位于同一目录。", + "startFailed": "未能启动操作。", + "webUploadFailed": "WebUI 文件上传失败。", + "firmwareDownloading": "正在下载固件…", + "firmwareStep": "[1/2] 固件 ", + "webUpgradeFailed": "WebUI 升级未完成:", + "hiddenPrefix": "[隐藏] ", + "officialSuffix": "(官方)", + "logFile": "日志文件:{path}\n", + "logFileSpaced": "\n日志文件:{path}\n", + "processKeyword": "进程关键词:{keyword}\n", + "sessionWaiting": "会话 ID:{id}\n正在等待输出…\n\n", + "expectedPattern": " 预期输出匹配:{pattern}\n", + "failurePattern": " 失败输出匹配:{pattern}\n", + "extractPattern": " 内容提取匹配:{pattern}\n", + "storedVariable": " 保存到变量:{name}.*\n", + "exitCode": "退出码:{code}\n", + "extractedLine": "提取内容:{value}\n", + "extractedBlock": "\n提取内容:\n{value}\n", + "sshError": "\n执行错误:{message}\n", + "executionFailed": "执行未完成:{message}\n", + "stopFailed": "未能确认服务已停止:{message}", + "firmwareMissing": "找不到固件文件:{path}", + "wwwMissing": "找不到 WebUI 文件:{path}", + "directoryUnreadable": "无法读取文件夹:{path}", + "firmwareDirMissing": "文件夹中没有固件 .bin 文件:{path}", + "wwwDirMissing": "找不到 WebUI 文件:{path}/www.bin", + "dnsFailed": "设备无法解析服务器地址:{host}", + "tcpFailed": "设备无法连接到服务器:{host}:{port}", + "httpFailed": "设备未能从服务器获取内容:{message}", + "httpStatus": "服务器返回错误(HTTP {status})。", + "downloadHttpStatus": "下载失败(HTTP {status})。", + "sshStopping": "进程仍在运行,正在请求强制停止…\n", + "stopUnconfirmed": "已发送强制停止请求,进程是否停止尚未确认。请检查进程状态。", + "credentials": "用户名或密码错误。", + "oldPassword": "当前密码错误,请重新输入。", + "sdUnavailable": "SD 卡尚未就绪,请检查插卡和挂载状态。", + "sdMounted": "SD 卡已经可以使用,无需重复挂载。", + "fileMissing": "找不到这个文件,请刷新文件列表。", + "directoryMissing": "找不到这个文件夹,请刷新文件列表。", + "rootDirectory": "不能删除存储根目录,请选择其中的文件或文件夹。", + "fileInfo": "无法读取文件信息。请检查存储设备后刷新列表。", + "unknownError": "操作未能完成。请查看详细原因。", + "invalidInput": "提交的信息不符合要求,请检查相关设置。", + "notFound": "找不到所需项目,请刷新列表检查它是否仍然存在。", + "permission": "当前账户没有执行此操作的权限。", + "busy": "设备正在处理其他操作,请等待当前操作结束。", + "timeout": "未在规定时间内收到完整响应,无法确认结果。请先检查当前状态。", + "resultUnknown": "未收到完整确认,操作结果未知。请先检查当前状态,不要重复执行。", + "memory": "设备可用内存不足,暂时无法完成操作。", + "internal": "设备处理请求时发生错误,请查看详细原因。", + "unsupported": "当前设备不支持此操作。", + "hardware": "设备未能完成硬件操作,请检查相关硬件状态。", + "connection": "无法连接到设备或目标服务,请检查网络连接。", + "auth": "身份验证未通过,请检查登录信息或重新登录。", + "invalidResponse": "设备返回的内容无法识别,操作结果未确认。", + "details": "详细原因:{detail}", + "deleteSummary": "删除结果:{success} 项成功,{fail} 项失败或未确认。", + "downloadSummary": "已向浏览器发起 {success} 项下载,{fail} 项未能发起。请在浏览器中确认保存结果。", + "uploadSummary": "上传结果:{success} 项已上传,{fail} 项失败或未确认;{invalid} 个配置包未通过验证。上传不代表配置已应用。", + "ledSummary": "关闭灯光结果:{success} 项成功,{fail} 项失败或未确认。", + "uploaded": "文件已上传。", + "packVerified": "已上传,签名验证通过;尚未应用。", + "packInvalid": "文件已上传,但配置包验证未通过,不能应用。", + "downloadStarted": "已向浏览器发起下载,请在浏览器中确认保存结果。", + "hiddenNetwork": "隐藏网络", + "wifiPassword": "请输入“{ssid}”的密码;开放网络可留空:", + "logConnected": "实时日志连接已建立", + "logDisconnected": "实时日志连接已断开,等待重新连接", + "sshSubmissionUnknown": "未收到命令受理确认,无法确定是否已经提交。请查看日志或进程状态,不要直接重复执行。", + "sshDiagnostics": "返回状态:{status};退出码:{code}", + "sshUnknown": "无法确认命令结果,请查看输出和状态详情。", + "sshTimeout": "命令执行超时,请查看输出确认实际执行情况。", + "sshCancelled": "取消处理已结束;远端命令是否终止尚未确认。", + "sshFailureOutput": "命令输出命中了配置的失败条件,请查看输出。", + "sshExpectedMissing": "命令已结束,但未检测到配置的预期输出。", + "sshExpectedFound": "已检测到预期输出,等待最终执行结果。", + "sshFailed": "命令执行失败,请查看输出和退出码。", + "sshSuccess": "命令执行成功。", + "lpmuProbeFailed": "LPMU 网络检测失败,电源状态未知。", + "lpmuReachable": "LPMU 网络可达;此检测不能确认电源状态。", + "lpmuUnreachable": "LPMU 网络不可达,无法据此确认是否已关机。", + "retry": "重试", + "terminalLoadFailed": "终端组件加载失败。请检查网络后重试。", + "terminalRestoring": "正在恢复终端会话,请等待连接确认。", + "terminalRestored": "终端会话已恢复;之前的命令未自动重发。", + "terminalRestoreTimeout": "终端会话恢复超时,尚未确认连接。", + "terminalRestoreFailed": "终端会话未能恢复,请重新连接。", + "noInitialColor": "没有可恢复的初始颜色配置。", + "serviceStarted": "服务“{name}”已启动。", + "serviceStopped": "服务“{name}”已停止。", + "serviceRestarted": "服务“{name}”已重启。", + "ruleCreated": "规则“{id}”已创建。", + "ruleUpdated": "规则“{id}”已更新。" +}, + + runtimeRepair: { + configLoading: '配置正在加载,请稍后刷新。', + confirmFingerprint: '请通过可信渠道核对以下服务器指纹。确认信任此指纹并继续连接?', + saved: '已保存', + "showDashboard": "在首页显示", + "allowManual": "允许手动执行", + "conditionsPreserved": "手动模式保留自动条件,切回自动后从下一次评估开始生效。", + "saveFailed": "保存失败,草稿已保留", + "saveUnknown": "保存结果未确认,请重新读取核对,勿重复提交。", + "mirrorWarning": "已保存,但备用副本未同步;请勿移除 SD 卡。", + "revision_conflict": "配置已被其他操作修改,请重新读取后合并草稿。", + "source_read_only": "此配置来源当前只读,未修改原文件。", + "recovery_required": "配置需要恢复核对,自动执行已暂停。", + "commit_unknown": "保存结果未确认,需要恢复核对。", + "execution_busy": "规则正在执行,当前操作不可用。", + "service_busy": "服务正在运行或状态未确认,请先核实并停止服务。", + "busy_retired_config": "旧配置仍在使用,请稍后重试。", + "disabled": "已禁用", + "manual": "手动", + "automatic": "自动", + "referenceUnresolved": "引用尚未解析", + "unknown": "状态未确认", + "running": "进程运行中", + "ready": "已匹配就绪日志", + "checking": "正在检查就绪日志", + "starting": "正在启动", + "stopping": "正在停止", + "stopped": "进程已确认停止", + "failed": "匹配到失败日志", + "timeout": "就绪检查超时", + "lastKnown": "上次状态", + "confirmedAt": "上次确认(开机后)", + "stateEvidence": "状态依据", + "startBlocked": "当前不允许启动:请检查启用、手动权限及服务状态。", + "outcomeUnknown": "远端结果未确认,可能仍在运行。请查询核实后再操作。", + "confirmStop": "确认停止远端服务?", + "confirmStopAutomatic": "确认停止远端服务?自动规则仍启用且条件满足时,下一次评估可能再次启动。若需保持停止,请先禁用自动规则。", + "refresh_required": "页面版本过旧,请刷新后编辑。" +}, + // 通用 common: { confirm: '确认', @@ -257,7 +512,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { lpmu: 'LPMU', agxRunning: 'AGX 运行中', agxStopped: 'AGX 已关闭', - lpmuDetecting: 'LPMU 检测中', + lpmuDetecting: "检测结果未知", usbMux: 'USB 切换', widgetManager: '组件管理', @@ -307,21 +562,21 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { agxPowerOnSuccess: 'AGX 已上电', agxPowerOffSuccess: 'AGX 已断电', agxPowerFail: 'AGX 操作失败', - lpmuRunning: 'LPMU 运行中', - lpmuStopped: 'LPMU 已关闭', - lpmuOnlineTitle: 'LPMU 在线 (ping 10.10.99.99 可达)\n点击触发电源按钮', - lpmuOfflineTitle: 'LPMU 离线 (ping 10.10.99.99 不可达)\n点击触发电源按钮', + lpmuRunning: "网络可达", + lpmuStopped: "网络不可达", + lpmuOnlineTitle: "LPMU 网络可达;此检测不能确认电源状态。", + lpmuOfflineTitle: "LPMU 网络不可达,无法据此确认是否已关机。", lpmuDetectingTitle: '正在检测 LPMU 状态...\n最多等待 80 秒', - lpmuUnknownTitle: 'LPMU 状态未知\n点击触发电源按钮', + lpmuUnknownTitle: "LPMU 网络检测失败,电源状态未知。", statusFetching: '状态获取中', lpmuTriggerConfirm: '确定要触发 LPMU 电源按钮吗?\n\n这将发送一个脉冲信号,效果类似按物理电源按钮。', lpmuTriggering: 'LPMU 电源触发中...', lpmuTriggerSuccess: 'LPMU 电源已触发,开始检测状态...', lpmuTriggerFail: 'LPMU 触发失败', - lpmuOnlineSuccess: 'LPMU 已上线', - lpmuOfflineSuccess: 'LPMU 已关闭', - lpmuStartupTimeout: 'LPMU 开机检测超时,认定为已关闭', - lpmuShutdownTimeout: 'LPMU 关机检测超时,设备可能仍在运行' + lpmuOnlineSuccess: "LPMU 网络可达;此检测不能确认电源状态。", + lpmuOfflineSuccess: "LPMU 网络不可达,无法据此确认是否已关机。", + lpmuStartupTimeout: "LPMU 网络不可达,无法据此确认是否已关机。", + lpmuShutdownTimeout: "LPMU 网络可达;此检测不能确认电源状态。" }, // 风扇控制 @@ -1087,7 +1342,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { serviceSuccess: '服务 {name} {action} 成功', // 电压保护 voltageProtectionEnabled: '电压保护已启用', - lowVoltageWarning: '低电压警告: {voltage}V ({countdown}s)', + lowVoltageWarning: "输入电压过低:{voltage} V,关机倒计时剩余 {countdown} 秒。", voltageProtectionTriggered: '电压保护已触发', voltageRecovering: '电压恢复中: {voltage}V', voltageProtectionDisabled: '电压保护已禁用', @@ -1117,7 +1372,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { firmwareWriteComplete: '固件写入完成!', webuiWriteComplete: 'WebUI 写入完成!', webuiUpgradeSkipped: 'WebUI 升级跳过: {msg}', - nohupStripped: '已自动去除命令中多余的 nohup 包装(后端会自动添加)', + nohupStripped: "已移除重复的后台运行参数,系统会自动在后台执行此命令。", saveCommandFailedMsg: '保存指令失败: {msg}', deleteCommandFailedMsg: '删除指令失败: {msg}', fillServerInfo: '请填写完整的服务器信息', @@ -1416,12 +1671,12 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { commandSuccess: '命令执行成功', commandMatchFailed: '命令执行完成,模式匹配失败', commandTimeout: '命令执行超时', - commandCompletedCode: '命令执行完成,退出码: {code}', + commandCompletedCode: "命令未成功完成,退出码:{code}。请查看命令输出。", execError: '执行出错', execErrorMsg: '执行出错: {msg}', - commandCancelled: '命令已取消', + commandCancelled: '取消处理已结束,远端结果未确认', hostFingerprintDeleted: '已删除主机指纹', - hostInfoEmpty: '主机信息为空', + hostInfoEmpty: "没有找到此主机的连接配置,请检查主机设置。", testingConnection: '正在测试连接 {host}...', cannotGetHostInfo: '无法获取主机信息', connectionSuccess: '连接 {host} 成功!', @@ -1465,9 +1720,9 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { device: { agxRunning: 'AGX 运行中', agxStopped: 'AGX 已关闭', - lpmuRunning: 'LPMU 运行中', - lpmuStopped: 'LPMU 已关闭', - lpmuDetecting: '状态获取中', + lpmuRunning: "网络可达", + lpmuStopped: "网络不可达", + lpmuDetecting: "检测结果未知", lpmuUnknown: 'LPMU 状态未知', lpmuOnlineHint: 'LPMU 在线 (ping 10.10.99.99 可达)\n点击触发电源按钮', lpmuOfflineHint: 'LPMU 离线 (ping 10.10.99.99 不可达)\n点击触发电源按钮', @@ -1793,8 +2048,8 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { patternMatchSuccess: '模式匹配成功!', expectPatternMatch: '期望模式匹配: 是', failPatternMatch: '失败模式匹配: 是', - failMatchedTrue: 'true (检测到错误)', - failMatchedFalse: 'false', + failMatchedTrue: "已检测到失败条件", + failMatchedFalse: "未检测到失败条件", extractedContent: '提取内容', cancelledExecution: '已取消执行', error: '错误', @@ -2798,8 +3053,8 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { unbindSuccess: '温度变量绑定已解除', unbindFailed: '解绑失败', dutyOrderError: '最小占空比不能大于最大占空比', - hysteresisRangeError: '温度迟滞必须在 0-20°C 范围内', - intervalRangeError: '最小间隔必须在 500-30000ms 范围内', + hysteresisRangeError: "调速温差(温度迟滞)必须在 0–20°C 范围内。", + intervalRangeError: "两次调速的最小间隔必须在 0.5–30 秒之间。", curveApplied: '风扇 {id} 曲线已应用并保存', applyCurveFailed: '应用曲线失败', curveExported: '风扇 {id} 曲线配置已导出(本地 + SD 卡 {path})', @@ -3122,6 +3377,45 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { }, // PKI/安全配置 + pkiRepair: { + "unknown": "未知/待确认", + "none": "未安装设备证书", + "invalid": "证书无法解析", + "time_unverified": "有效期:待校时确认", + "not_yet_valid": "有效期:尚未生效", + "valid": "有效期:当前在有效期内", + "expired": "有效期:已过期", + "stored": "已保存", + "missing": "缺少", + "key": "私钥", + "certificate": "设备证书", + "clientCa": "客户端验证 CA", + "running": "运行中", + "stopped": "未运行", + "restart": "存储材料已变更。运行中的服务仍使用旧材料;请重启设备以应用。新材料须满足启动条件,删除凭证不等于在线吊销。", + "activeFingerprint": "活动证书 SHA-256", + "deviceTime": "设备时间", + "synced": "已同步", + "unsynced": "未同步", + "timeUnknown": "设备时间读取失败,请刷新重试", + "syncBrowser": "用当前电脑时间校时(来源:浏览器)", + "empty": "请输入 PEM 内容", + "saved": "已保存,请查看有效期和 HTTPS 实际状态。", + "unconfirmed": "未能确认安装结果,请刷新状态核对后再决定是否重试。", + "lessDay": "不到 1 天后过期", + "expiredLessDay": "已过期不足 1 天", + "block_time_not_ready": "设备时间未就绪", + "block_private_key_missing": "缺少私钥", + "block_private_key_invalid": "私钥异常", + "block_certificate_missing": "缺少设备证书", + "block_certificate_invalid": "设备证书异常", + "block_key_mismatch": "证书与密钥不匹配", + "block_not_yet_valid": "证书尚未生效", + "block_expired": "证书已过期", + "block_ca_missing": "缺少客户端验证 CA", + "block_ca_invalid": "客户端验证 CA 异常", + "block_storage_error": "存储结果不确定,请重启后核对材料" +}, pkiPage: { signatureVerified: '签名验证通过', configImported: '配置包已导入', @@ -3369,6 +3663,25 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { // 终端页面 terminal: { + sshCapacity: "结果通知通道暂时繁忙,本次 SSH 连接未启动,请稍后重试。", + sshCreateFailed: "未能创建 SSH 会话,请稍后重试。", + sshOpenFailed: "未能启动远端交互式终端,请检查远端是否允许此类连接。", + sshStartupClosed: "SSH 会话在启动期间已结束,请检查远端状态后重新连接。", + sshStatusFailed: "SSH 状态通知未能完成,连接状态尚未确认,请重新连接。", + sshOutputIncomplete: "网页 SSH 输出不完整,远端执行结果尚未确认。请检查远端状态,不要直接重发命令。", + sshClosed: "SSH 会话已结束。", + sshClosing: "正在结束 SSH 会话,请等待确认。", + sshConnecting: "正在建立 SSH 连接…", + sshReady: "SSH 交互式终端已就绪。", + sshServiceStopping: "服务正在停止,本次请求未被接受。", + sshControlUnsupported: "不支持此 SSH 信号,会话仍可继续使用。", + sshControlInvalid: "SSH 控制参数无效,会话仍可继续使用。", + sshControlFailed: "本次 SSH 请求失败,输入未自动重发。", + sshChannelUnknown: "SSH 通道异常结束,远端执行结果尚未确认。", + sshWrongOwner: "此连接不属于当前有效的 SSH 会话。", + sshBusy: "已有 SSH 会话,本次连接请求未被接受。", + sshRequestRejected: "本次 SSH 请求未被接受。", + connecting: '正在连接到设备...', connected: '已连接到设备', helpHint: '输入 {help} 查看可用命令', diff --git a/components/ts_webui/web/js/router.js b/components/ts_webui/web/js/router.js index 16d762e..256f1c5 100644 --- a/components/ts_webui/web/js/router.js +++ b/components/ts_webui/web/js/router.js @@ -7,6 +7,9 @@ class Router { constructor() { this.routes = {}; this.currentPage = null; + this.appReady = false; + this.startupStarted = false; + this.navigation = null; // 需要 root 权限的页面(终端、自动化、指令) this.rootOnlyPages = ['/terminal', '/automation', '/commands']; @@ -15,7 +18,9 @@ class Router { this.publicPages = []; // 暂时没有公开页面 window.addEventListener('hashchange', () => this.navigate()); - window.addEventListener('load', () => this.navigate()); + window.addEventListener('load', () => this.start()); + window.addEventListener('languageReady', () => this.start()); + window.addEventListener('appReady', () => { this.appReady = true; this.start(); }); } register(path, loader) { @@ -42,27 +47,45 @@ class Router { return { allowed: true }; } - navigate(path = null) { - if (path) { + start() { + if (this.startupStarted || !this.appReady || !window.i18n?.isReady()) return; + this.startupStarted = true; + const pending = this.navigate(); + const navigation = this.navigation; + return pending.then(ok => { + if (!ok && this.navigation === navigation) this.startupStarted = false; + }); + } + + async navigate(path = null) { + if (path && (window.location.hash.slice(1) || '/') !== path) { window.location.hash = path; - return; - } - - let hash = window.location.hash.slice(1) || '/'; - - // 页面切换前的清理 - 停止定时器等 - if (typeof stopDeviceStateMonitor === 'function') { - stopDeviceStateMonitor(); - } - // 取消系统页快捷操作定时器,避免切走后仍触发 refreshQuickActions - if (typeof stopSystemPageTimers === 'function') { - stopSystemPageTimers(); + return false; } - // 离开终端页时主动断开 WebSocket,避免 1006 异常关闭 - if (typeof destroyWebTerminal === 'function') { - destroyWebTerminal(); - } - + if (!this.appReady || !window.i18n?.isReady()) return false; + const hash = window.location.hash.slice(1) || '/'; + // Dispose synchronously before the next loader starts. A late loader never + // runs global cleanup and cannot dispose resources belonging to its successor. + this.navigation?.dispose(); + const disposers = []; + const navigation = { + active: true, + isCurrent: () => this.navigation === navigation && navigation.active, + onDispose: fn => { if (navigation.active) disposers.push(fn); else fn(); }, + dispose: () => { + if (!navigation.active) return; + navigation.active = false; + for (const fn of disposers) fn(); + } + }; + this.navigation = navigation; + navigation.onDispose(() => { + if (typeof stopDeviceStateMonitor === 'function') stopDeviceStateMonitor(); + if (typeof stopSystemPageTimers === 'function') stopSystemPageTimers(); + if (typeof stopDataWidgetsAutoRefresh === 'function') stopDataWidgetsAutoRefresh(); + if (typeof stopNetworkLpmuAccessPolling === 'function') stopNetworkLpmuAccessPolling(); + if (typeof destroyWebTerminal === 'function') destroyWebTerminal(); + }); // 检查访问权限 const access = this.checkAccess(hash); if (!access.allowed) { @@ -96,7 +119,21 @@ class Router { const loader = this.routes[hash] || this.routes['/']; if (loader) { this.currentPage = loader; - loader(); + try { + await loader(); + return navigation.isCurrent(); + } catch (error) { + if (!navigation.isCurrent()) return false; + navigation.dispose(); + const content = document.getElementById('page-content'); + content.replaceChildren(); + const message = document.createElement('p'); message.textContent = t('promptRepair.pageLoadFailed'); + const retry = document.createElement('button'); retry.textContent = t('promptRepair.retry'); + retry.onclick = () => this.navigate(); + content.append(message, retry); + console.error('Page initialization failed:', error); + return false; + } } } diff --git a/components/ts_webui/web/js/terminal.js b/components/ts_webui/web/js/terminal.js index 8b4475a..b1783eb 100644 --- a/components/ts_webui/web/js/terminal.js +++ b/components/ts_webui/web/js/terminal.js @@ -4,42 +4,36 @@ */ /** - * 按需加载 xterm.js 及其插件(从 CDN) + * 按需加载 xterm.js 及其插件(设备本地资源) * 仅在首次打开终端页面时触发,后续调用直接返回 */ const _xtermReady = (function() { let _promise = null; - function loadCSS(href) { - return new Promise(function(resolve, reject) { - if (document.querySelector('link[href="' + href + '"]')) { resolve(); return; } - var link = document.createElement('link'); - link.rel = 'stylesheet'; - link.href = href; - link.onload = resolve; - link.onerror = reject; - document.head.appendChild(link); - }); - } - function loadScript(src) { - return new Promise(function(resolve, reject) { - if (document.querySelector('script[src="' + src + '"]')) { resolve(); return; } - var s = document.createElement('script'); - s.src = src; - s.onload = resolve; - s.onerror = reject; - document.head.appendChild(s); + function loadResource(url, css) { + return new Promise((resolve, reject) => { + const selector = css ? 'link[href="' + url + '"]' : 'script[src="' + url + '"]'; + const existing = document.querySelector(selector); + if (existing?.dataset.ready === 'true') { resolve(); return; } + if (existing) existing.remove(); + const node = document.createElement(css ? 'link' : 'script'); + if (css) { node.rel = 'stylesheet'; node.href = url; } else node.src = url; + const timer = setTimeout(() => finish(false), 15000); + function finish(ok) { + clearTimeout(timer); node.onload = node.onerror = null; + if (ok) { node.dataset.ready = 'true'; resolve(); } + else { node.remove(); reject(new Error('Terminal resource unavailable: ' + url)); } + } + node.onload = () => finish(true); node.onerror = () => finish(false); + document.head.appendChild(node); }); } - return function ensureXtermLoaded() { if (_promise) return _promise; - if (typeof Terminal !== 'undefined' && typeof FitAddon !== 'undefined') { - return (_promise = Promise.resolve()); - } - _promise = loadCSS('https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css') - .then(function() { return loadScript('https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js'); }) - .then(function() { return loadScript('https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js'); }); + _promise = loadResource('/vendor/xterm/xterm.css?v=' + encodeURIComponent(window.TS_ASSET_VERSION), true) + .then(() => loadResource('/vendor/xterm/xterm.min.js?v=' + encodeURIComponent(window.TS_ASSET_VERSION), false)) + .then(() => loadResource('/vendor/xterm/fit.min.js?v=' + encodeURIComponent(window.TS_ASSET_VERSION), false)) + .catch(error => { _promise = null; throw error; }); return _promise; }; })(); @@ -60,6 +54,10 @@ class WebTerminal { // SSH Shell 模式 this.sshMode = false; this.sshConnecting = false; + this.sshDisconnecting = false; + this.restoring = false; + this.restoreTimer = null; + this.destroyed = false; } /** @@ -72,8 +70,19 @@ class WebTerminal { return false; } - // 按需加载 xterm.js(首次访问终端页面时从 CDN 拉取) - await _xtermReady(); + // 按需加载 xterm.js(首次访问终端页面时从设备加载) + try { await _xtermReady(); } + catch (error) { + if (this.destroyed) return false; + console.error(error); + container.replaceChildren(); + const message = document.createElement('p'); message.textContent = t('promptRepair.terminalLoadFailed'); + const retry = document.createElement('button'); retry.className = 'btn'; retry.textContent = t('promptRepair.retry'); + retry.onclick = () => loadTerminalPage(); + container.append(message, retry); + return false; + } + if (this.destroyed) return false; // 创建 xterm.js 终端 this.terminal = new Terminal({ @@ -141,7 +150,7 @@ class WebTerminal { */ setupInputHandler() { this.terminal.onData(data => { - if (!this.connected) return; + if (!this.connected || this.sshConnecting || this.sshDisconnecting) return; // SSH Shell 模式 if (this.sshMode) { @@ -297,26 +306,32 @@ class WebTerminal { * 连接到 WebSocket */ connect() { + if (this.destroyed) return; + if (this.ws) this.disconnect(); const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsUrl = `${protocol}//${window.location.host}/ws`; - this.ws = new WebSocket(wsUrl); + const ws = new WebSocket(wsUrl); + this.ws = ws; + const current = () => !this.destroyed && this.ws === ws; this.pingInterval = null; - this.ws.onopen = () => { + ws.onopen = () => { + if (!current()) return; console.log('Terminal WebSocket connected'); // 发送终端启动请求 - this.ws.send(JSON.stringify({ type: 'terminal_start' })); + ws.send(JSON.stringify({ type: 'terminal_start' })); // 启动心跳机制 this.pingInterval = setInterval(() => { - if (this.ws && this.ws.readyState === WebSocket.OPEN) { - this.ws.send(JSON.stringify({ type: 'ping' })); + if (current() && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'ping' })); } }, 15000); // 每15秒发送心跳 }; - this.ws.onmessage = (event) => { + ws.onmessage = (event) => { + if (!current()) return; try { const msg = JSON.parse(event.data); this.handleMessage(msg); @@ -325,9 +340,12 @@ class WebTerminal { } }; - this.ws.onclose = (event) => { + ws.onclose = (event) => { + if (!current()) return; console.log('Terminal WebSocket disconnected, code:', event.code); this.connected = false; + this.sshMode = this.sshConnecting = this.sshDisconnecting = false; + if (this.restoring) this.finishRestore(false); // 清除心跳 if (this.pingInterval) { @@ -341,7 +359,7 @@ class WebTerminal { if (event.code !== 1000) { // 非正常关闭 this.writeln('\x1b[33m' + (typeof t === 'function' ? t('terminal.reconnectIn') : '5秒后尝试重新连接...') + '\x1b[0m'); const tryReconnect = () => { - if (this.connected) return; + if (!current() || this.connected) return; if (document.visibilityState !== 'visible') { document.addEventListener('visibilitychange', function handler() { document.removeEventListener('visibilitychange', handler); @@ -356,7 +374,8 @@ class WebTerminal { } }; - this.ws.onerror = (error) => { + ws.onerror = (error) => { + if (!current()) return; console.error('Terminal WebSocket error:', error); this.writeln('\r\n\x1b[1;31m' + (typeof t === 'function' ? t('terminal.connectionError') : '连接错误') + '\x1b[0m'); }; @@ -365,9 +384,20 @@ class WebTerminal { /** * 处理 WebSocket 消息 */ + finishRestore(ok, timeout = false) { + clearTimeout(this.restoreTimer); this.restoreTimer = null; + this.restoring = false; + const key = ok ? 'terminalRestored' : timeout ? 'terminalRestoreTimeout' : 'terminalRestoreFailed'; + this.writeln(t('promptRepair.' + key)); + showToast(t('promptRepair.' + key), ok ? 'success' : 'warning'); + } + handleMessage(msg) { + if (this.destroyed) return; switch (msg.type) { case 'connected': + if (this.sshMode || this.sshConnecting || this.sshDisconnecting) return; + if (this.restoring) this.finishRestore(true); this.connected = true; this.prompt = msg.prompt || 'tianshan> '; this.writeln('\x1b[1;32m' + (typeof t === 'function' ? t('terminal.connected') : '已连接到设备') + '\x1b[0m'); @@ -384,17 +414,28 @@ class WebTerminal { break; case 'done': + if (this.sshMode || this.sshConnecting || this.sshDisconnecting) return; // 命令执行完成 this.writePrompt(); break; case 'error': { const errMsg = msg.message || (typeof t === 'function' ? t('terminal.unknownError') : '未知错误'); + if (this.sshMode || this.sshConnecting || this.sshDisconnecting) { + this.writeln('\x1b[1;31m' + this.sshMessageText(errMsg) + '\x1b[0m'); + if (this.sshConnecting && !this.sshMode) { this.sshConnecting = false; this.writePrompt(); } + break; // request failure is not an operation terminal + } if (errMsg.indexOf('Not a terminal session') >= 0 && this.ws && this.ws.readyState === WebSocket.OPEN) { - this.ws.send(JSON.stringify({ type: 'terminal_start' })); - const toast = typeof showToast === 'function' ? showToast : function(m) { console.log(m); }; - toast(typeof t === 'function' ? t('terminal.sessionRestored') : '会话已恢复,请重试', 'success'); + if (!this.restoring) { + this.restoring = true; this.connected = false; + this.ws.send(JSON.stringify({type: 'terminal_start'})); + showToast(t('promptRepair.terminalRestoring'), 'info'); + const restoringSocket = this.ws; + this.restoreTimer = setTimeout(() => { if (!this.destroyed && this.ws === restoringSocket && this.restoring) this.finishRestore(false, true); }, 10000); + } } else { + if (this.restoring) this.finishRestore(false); this.writeln('\x1b[1;31m' + (typeof t === 'function' ? t('terminal.errorLabel') : '错误') + ': ' + errMsg + '\x1b[0m'); this.writePrompt(); } @@ -423,6 +464,7 @@ class WebTerminal { case 'session_closed': this.connected = false; + this.sshMode = this.sshConnecting = this.sshDisconnecting = false; this.writeln('\x1b[33m' + (typeof t === 'function' ? t('terminal.sessionClosed') : '会话已关闭,请重新连接') + '\x1b[0m'); break; @@ -435,6 +477,7 @@ class WebTerminal { * 处理电压保护事件 */ handlePowerEvent(msg) { + if (this.destroyed || !this.terminal) return; const state = msg.state || 'UNKNOWN'; const voltage = msg.voltage ? msg.voltage.toFixed(2) : '?.??'; const countdown = msg.countdown || 0; @@ -493,6 +536,19 @@ class WebTerminal { } if (notification) { + const canRestoreLocalInput = + !this.destroyed && + this.connected && + this.ws && + this.ws.readyState === WebSocket.OPEN && + !this.sshMode && + !this.sshConnecting && + !this.sshDisconnecting && + !this.restoring; + if (!canRestoreLocalInput) { + this.writeln(`\r\n${color}${notification}\x1b[0m`); + return; + } // 保存当前输入状态 const savedBuffer = this.inputBuffer; const savedPosition = this.cursorPosition; @@ -570,10 +626,9 @@ class WebTerminal { startSshShell(params) { if (this.sshConnecting || this.sshMode) { this.writeln('\x1b[1;31m' + (typeof t === 'function' ? t('terminal.sshSessionInProgress') : 'SSH 会话已在进行中') + '\x1b[0m'); - this.writePrompt(); return; } - + if (!this.connected || !this.ws || this.ws.readyState !== WebSocket.OPEN) return; this.sshConnecting = true; const connMsg = typeof t === 'function' ? t('terminal.sshConnectingTo', { user: params.user, host: params.host, port: params.port }) : `正在连接到 ${params.user}@${params.host}:${params.port}...`; this.writeln(`\x1b[36m${connMsg}\x1b[0m`); @@ -604,29 +659,66 @@ class WebTerminal { /** * 处理 SSH 状态消息 */ + sshMessageText(message) { + const keys = { + "Missing host or user": "sshShellRequiresParams", + "SSH result delivery capacity unavailable": "sshCapacity", + "Failed to create SSH session": "sshCreateFailed", + "Failed to open shell": "sshOpenFailed", + "SSH shell closed during startup": "sshStartupClosed", + "SSH connection status delivery failed": "sshStatusFailed", + "SSH readiness delivery failed": "sshStatusFailed", + "SSH status delivery failed": "sshStatusFailed", + "SSH output delivery incomplete; remote command result is not confirmed": "sshOutputIncomplete", + "SSH session closed": "sshClosed", + "Closing SSH session...": "sshClosing", + "Connecting to SSH server...": "sshConnecting", + "SSH shell ready": "sshReady", + "Service is stopping": "sshServiceStopping", + 'Unsupported SSH signal': 'sshControlUnsupported', + 'Invalid SSH control parameters': 'sshControlInvalid', + 'SSH control request failed; input was not replayed': 'sshControlFailed', + 'SSH channel failed; remote result is not confirmed': 'sshChannelUnknown', + 'This connection does not own an active SSH session': 'sshWrongOwner', + 'Another SSH session is active': 'sshBusy', + 'SSH request rejected': 'sshRequestRejected' + }; + return keys[message] && typeof t === 'function' ? t('terminal.' + keys[message]) : message; + } + handleSshStatus(msg) { const status = msg.status; - const message = msg.message || ''; + const message = this.sshMessageText(msg.message || ''); switch (status) { case 'connecting': this.writeln(`\x1b[33m${message}\x1b[0m`); break; case 'connected': + if (!this.sshConnecting) return; + this.sshDisconnecting = false; this.sshMode = true; this.sshConnecting = false; this.writeln(`\x1b[1;32m${message}\x1b[0m`); this.writeln('\x1b[90m' + (typeof t === 'function' ? t('terminal.exitSshHint') : '(按 Ctrl+\\ 退出 SSH shell)') + '\x1b[0m'); this.writeln(''); break; - case 'closed': case 'disconnecting': + if (!this.sshMode) return; + this.sshDisconnecting = true; + this.writeln(`\r\n\x1b[33m${message}\x1b[0m`); + break; + case 'closed': + if (!this.sshMode && !this.sshConnecting) return; + this.sshDisconnecting = false; this.sshMode = false; this.sshConnecting = false; this.writeln(`\r\n\x1b[33m${message}\x1b[0m`); this.writePrompt(); break; case 'error': + if (!this.sshMode && !this.sshConnecting) return; + this.sshDisconnecting = false; this.sshMode = false; this.sshConnecting = false; this.writeln(`\x1b[1;31m${message}\x1b[0m`); @@ -686,6 +778,7 @@ class WebTerminal { * 断开连接 */ disconnect() { + clearTimeout(this.restoreTimer); this.restoring = false; // 清除心跳 if (this.pingInterval) { clearInterval(this.pingInterval); @@ -701,12 +794,14 @@ class WebTerminal { this.ws = null; } this.connected = false; + this.sshMode = this.sshConnecting = this.sshDisconnecting = false; } /** * 销毁终端 */ destroy() { + this.destroyed = true; this.disconnect(); if (this.terminal) { this.terminal.dispose(); diff --git a/components/ts_webui/web/vendor/xterm/LICENSE-fit b/components/ts_webui/web/vendor/xterm/LICENSE-fit new file mode 100644 index 0000000..8f17892 --- /dev/null +++ b/components/ts_webui/web/vendor/xterm/LICENSE-fit @@ -0,0 +1,19 @@ +Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/components/ts_webui/web/vendor/xterm/LICENSE-xterm b/components/ts_webui/web/vendor/xterm/LICENSE-xterm new file mode 100644 index 0000000..4472336 --- /dev/null +++ b/components/ts_webui/web/vendor/xterm/LICENSE-xterm @@ -0,0 +1,21 @@ +Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) +Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com) +Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/components/ts_webui/web/vendor/xterm/fit.min.js b/components/ts_webui/web/vendor/xterm/fit.min.js new file mode 100644 index 0000000..7384f10 --- /dev/null +++ b/components/ts_webui/web/vendor/xterm/fit.min.js @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})())); +//# sourceMappingURL=xterm-addon-fit.js.map \ No newline at end of file diff --git a/components/ts_webui/web/vendor/xterm/xterm.css b/components/ts_webui/web/vendor/xterm/xterm.css new file mode 100644 index 0000000..74acc26 --- /dev/null +++ b/components/ts_webui/web/vendor/xterm/xterm.css @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * @license MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + +/** + * Default styles for xterm.js + */ + +.xterm { + cursor: text; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +} + +.xterm.focus, +.xterm:focus { + outline: none; +} + +.xterm .xterm-helpers { + position: absolute; + top: 0; + /** + * The z-index of the helpers must be higher than the canvases in order for + * IMEs to appear on top. + */ + z-index: 5; +} + +.xterm .xterm-helper-textarea { + padding: 0; + border: 0; + margin: 0; + /* Move textarea out of the screen to the far left, so that the cursor is not visible */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -5; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; +} + +.xterm .composition-view { + /* TODO: Composition position got messed up somewhere */ + background: #000; + color: #FFF; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; +} + +.xterm .composition-view.active { + display: block; +} + +.xterm .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; + cursor: default; + position: absolute; + right: 0; + left: 0; + top: 0; + bottom: 0; +} + +.xterm .xterm-screen { + position: relative; +} + +.xterm .xterm-screen canvas { + position: absolute; + left: 0; + top: 0; +} + +.xterm .xterm-scroll-area { + visibility: hidden; +} + +.xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + top: 0; + left: -9999em; + line-height: normal; +} + +.xterm.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; +} + +.xterm.xterm-cursor-pointer, +.xterm .xterm-cursor-pointer { + cursor: pointer; +} + +.xterm.column-select.focus { + /* Column selection mode */ + cursor: crosshair; +} + +.xterm .xterm-accessibility, +.xterm .xterm-message { + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + z-index: 10; + color: transparent; + pointer-events: none; +} + +.xterm .live-region { + position: absolute; + left: -9999px; + width: 1px; + height: 1px; + overflow: hidden; +} + +.xterm-dim { + /* Dim should not apply to background, so the opacity of the foreground color is applied + * explicitly in the generated class and reset to 1 here */ + opacity: 1 !important; +} + +.xterm-underline-1 { text-decoration: underline; } +.xterm-underline-2 { text-decoration: double underline; } +.xterm-underline-3 { text-decoration: wavy underline; } +.xterm-underline-4 { text-decoration: dotted underline; } +.xterm-underline-5 { text-decoration: dashed underline; } + +.xterm-overline { + text-decoration: overline; +} + +.xterm-overline.xterm-underline-1 { text-decoration: overline underline; } +.xterm-overline.xterm-underline-2 { text-decoration: overline double underline; } +.xterm-overline.xterm-underline-3 { text-decoration: overline wavy underline; } +.xterm-overline.xterm-underline-4 { text-decoration: overline dotted underline; } +.xterm-overline.xterm-underline-5 { text-decoration: overline dashed underline; } + +.xterm-strikethrough { + text-decoration: line-through; +} + +.xterm-screen .xterm-decoration-container .xterm-decoration { + z-index: 6; + position: absolute; +} + +.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer { + z-index: 7; +} + +.xterm-decoration-overview-ruler { + z-index: 8; + position: absolute; + top: 0; + right: 0; + pointer-events: none; +} + +.xterm-decoration-top { + z-index: 2; + position: relative; +} diff --git a/components/ts_webui/web/vendor/xterm/xterm.min.js b/components/ts_webui/web/vendor/xterm/xterm.min.js new file mode 100644 index 0000000..d7bd63f --- /dev/null +++ b/components/ts_webui/web/vendor/xterm/xterm.min.js @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/xterm@5.3.0/lib/xterm.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var i=t();for(var s in i)("object"==typeof exports?exports:e)[s]=i[s]}}(self,(()=>(()=>{"use strict";var e={4567:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.AccessibilityManager=void 0;const n=i(9042),o=i(6114),a=i(9924),h=i(844),c=i(5596),l=i(4725),d=i(3656);let _=t.AccessibilityManager=class extends h.Disposable{constructor(e,t){super(),this._terminal=e,this._renderService=t,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=document.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=document.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let e=0;ethis._handleBoundaryFocus(e,0),this._bottomBoundaryFocusListener=e=>this._handleBoundaryFocus(e,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=document.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new a.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((e=>this._handleResize(e.rows)))),this.register(this._terminal.onRender((e=>this._refreshRows(e.start,e.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((e=>this._handleChar(e)))),this.register(this._terminal.onLineFeed((()=>this._handleChar("\n")))),this.register(this._terminal.onA11yTab((e=>this._handleTab(e)))),this.register(this._terminal.onKey((e=>this._handleKey(e.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this._screenDprMonitor=new c.ScreenDprMonitor(window),this.register(this._screenDprMonitor),this._screenDprMonitor.setListener((()=>this._refreshRowsDimensions())),this.register((0,d.addDisposableDomListener)(window,"resize",(()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,h.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let t=0;t0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=n.tooMuchOutput)),o.isMac&&this._liveRegion.textContent&&this._liveRegion.textContent.length>0&&!this._liveRegion.parentNode&&setTimeout((()=>{this._accessibilityContainer.appendChild(this._liveRegion)}),0))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0,o.isMac&&this._liveRegion.remove()}_handleKey(e){this._clearLiveRegion(),/\p{Control}/u.test(e)||this._charsToConsume.push(e)}_refreshRows(e,t){this._liveRegionDebouncer.refresh(e,t,this._terminal.rows)}_renderRows(e,t){const i=this._terminal.buffer,s=i.lines.length.toString();for(let r=e;r<=t;r++){const e=i.translateBufferLineToString(i.ydisp+r,!0),t=(i.ydisp+r+1).toString(),n=this._rowElements[r];n&&(0===e.length?n.innerText=" ":n.textContent=e,n.setAttribute("aria-posinset",t),n.setAttribute("aria-setsize",s))}this._announceCharacters()}_announceCharacters(){0!==this._charsToAnnounce.length&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,t){const i=e.target,s=this._rowElements[0===t?1:this._rowElements.length-2];if(i.getAttribute("aria-posinset")===(0===t?"1":`${this._terminal.buffer.lines.length}`))return;if(e.relatedTarget!==s)return;let r,n;if(0===t?(r=i,n=this._rowElements.pop(),this._rowContainer.removeChild(n)):(r=this._rowElements.shift(),n=i,this._rowContainer.removeChild(r)),r.removeEventListener("focus",this._topBoundaryFocusListener),n.removeEventListener("focus",this._bottomBoundaryFocusListener),0===t){const e=this._createAccessibilityTreeNode();this._rowElements.unshift(e),this._rowContainer.insertAdjacentElement("afterbegin",e)}else{const e=this._createAccessibilityTreeNode();this._rowElements.push(e),this._rowContainer.appendChild(e)}this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._terminal.scrollLines(0===t?-1:1),this._rowElements[0===t?1:this._rowElements.length-2].focus(),e.preventDefault(),e.stopImmediatePropagation()}_handleResize(e){this._rowElements[this._rowElements.length-1].removeEventListener("focus",this._bottomBoundaryFocusListener);for(let e=this._rowContainer.children.length;ee;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()}_createAccessibilityTreeNode(){const e=document.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e}_refreshRowsDimensions(){if(this._renderService.dimensions.css.cell.height){this._accessibilityContainer.style.width=`${this._renderService.dimensions.css.canvas.width}px`,this._rowElements.length!==this._terminal.rows&&this._handleResize(this._terminal.rows);for(let e=0;e{function i(e){return e.replace(/\r?\n/g,"\r")}function s(e,t){return t?"[200~"+e+"[201~":e}function r(e,t,r,n){e=s(e=i(e),r.decPrivateModes.bracketedPasteMode&&!0!==n.rawOptions.ignoreBracketedPasteMode),r.triggerDataEvent(e,!0),t.value=""}function n(e,t,i){const s=i.getBoundingClientRect(),r=e.clientX-s.left-10,n=e.clientY-s.top-10;t.style.width="20px",t.style.height="20px",t.style.left=`${r}px`,t.style.top=`${n}px`,t.style.zIndex="1000",t.focus()}Object.defineProperty(t,"__esModule",{value:!0}),t.rightClickHandler=t.moveTextAreaUnderMouseCursor=t.paste=t.handlePasteEvent=t.copyHandler=t.bracketTextForPaste=t.prepareTextForTerminal=void 0,t.prepareTextForTerminal=i,t.bracketTextForPaste=s,t.copyHandler=function(e,t){e.clipboardData&&e.clipboardData.setData("text/plain",t.selectionText),e.preventDefault()},t.handlePasteEvent=function(e,t,i,s){e.stopPropagation(),e.clipboardData&&r(e.clipboardData.getData("text/plain"),t,i,s)},t.paste=r,t.moveTextAreaUnderMouseCursor=n,t.rightClickHandler=function(e,t,i,s,r){n(e,t,i),r&&s.rightClickSelect(e),t.value=s.selectionText,t.select()}},7239:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ColorContrastCache=void 0;const s=i(1505);t.ColorContrastCache=class{constructor(){this._color=new s.TwoKeyMap,this._css=new s.TwoKeyMap}setCss(e,t,i){this._css.set(e,t,i)}getCss(e,t){return this._css.get(e,t)}setColor(e,t,i){this._color.set(e,t,i)}getColor(e,t){return this._color.get(e,t)}clear(){this._color.clear(),this._css.clear()}}},3656:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.addDisposableDomListener=void 0,t.addDisposableDomListener=function(e,t,i,s){e.addEventListener(t,i,s);let r=!1;return{dispose:()=>{r||(r=!0,e.removeEventListener(t,i,s))}}}},6465:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.Linkifier2=void 0;const n=i(3656),o=i(8460),a=i(844),h=i(2585);let c=t.Linkifier2=class extends a.Disposable{get currentLink(){return this._currentLink}constructor(e){super(),this._bufferService=e,this._linkProviders=[],this._linkCacheDisposables=[],this._isMouseOut=!0,this._wasResized=!1,this._activeLine=-1,this._onShowLinkUnderline=this.register(new o.EventEmitter),this.onShowLinkUnderline=this._onShowLinkUnderline.event,this._onHideLinkUnderline=this.register(new o.EventEmitter),this.onHideLinkUnderline=this._onHideLinkUnderline.event,this.register((0,a.getDisposeArrayDisposable)(this._linkCacheDisposables)),this.register((0,a.toDisposable)((()=>{this._lastMouseEvent=void 0}))),this.register(this._bufferService.onResize((()=>{this._clearCurrentLink(),this._wasResized=!0})))}registerLinkProvider(e){return this._linkProviders.push(e),{dispose:()=>{const t=this._linkProviders.indexOf(e);-1!==t&&this._linkProviders.splice(t,1)}}}attachToDom(e,t,i){this._element=e,this._mouseService=t,this._renderService=i,this.register((0,n.addDisposableDomListener)(this._element,"mouseleave",(()=>{this._isMouseOut=!0,this._clearCurrentLink()}))),this.register((0,n.addDisposableDomListener)(this._element,"mousemove",this._handleMouseMove.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mousedown",this._handleMouseDown.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mouseup",this._handleMouseUp.bind(this)))}_handleMouseMove(e){if(this._lastMouseEvent=e,!this._element||!this._mouseService)return;const t=this._positionFromMouseEvent(e,this._element,this._mouseService);if(!t)return;this._isMouseOut=!1;const i=e.composedPath();for(let e=0;e{null==e||e.forEach((e=>{e.link.dispose&&e.link.dispose()}))})),this._activeProviderReplies=new Map,this._activeLine=e.y);let r=!1;for(const[i,n]of this._linkProviders.entries())t?(null===(s=this._activeProviderReplies)||void 0===s?void 0:s.get(i))&&(r=this._checkLinkProviderResult(i,e,r)):n.provideLinks(e.y,(t=>{var s,n;if(this._isMouseOut)return;const o=null==t?void 0:t.map((e=>({link:e})));null===(s=this._activeProviderReplies)||void 0===s||s.set(i,o),r=this._checkLinkProviderResult(i,e,r),(null===(n=this._activeProviderReplies)||void 0===n?void 0:n.size)===this._linkProviders.length&&this._removeIntersectingLinks(e.y,this._activeProviderReplies)}))}_removeIntersectingLinks(e,t){const i=new Set;for(let s=0;se?this._bufferService.cols:s.link.range.end.x;for(let e=n;e<=o;e++){if(i.has(e)){r.splice(t--,1);break}i.add(e)}}}}_checkLinkProviderResult(e,t,i){var s;if(!this._activeProviderReplies)return i;const r=this._activeProviderReplies.get(e);let n=!1;for(let t=0;tthis._linkAtPosition(e.link,t)));e&&(i=!0,this._handleNewLink(e))}if(this._activeProviderReplies.size===this._linkProviders.length&&!i)for(let e=0;ethis._linkAtPosition(e.link,t)));if(r){i=!0,this._handleNewLink(r);break}}return i}_handleMouseDown(){this._mouseDownLink=this._currentLink}_handleMouseUp(e){if(!this._element||!this._mouseService||!this._currentLink)return;const t=this._positionFromMouseEvent(e,this._element,this._mouseService);t&&this._mouseDownLink===this._currentLink&&this._linkAtPosition(this._currentLink.link,t)&&this._currentLink.link.activate(e,this._currentLink.link.text)}_clearCurrentLink(e,t){this._element&&this._currentLink&&this._lastMouseEvent&&(!e||!t||this._currentLink.link.range.start.y>=e&&this._currentLink.link.range.end.y<=t)&&(this._linkLeave(this._element,this._currentLink.link,this._lastMouseEvent),this._currentLink=void 0,(0,a.disposeArray)(this._linkCacheDisposables))}_handleNewLink(e){if(!this._element||!this._lastMouseEvent||!this._mouseService)return;const t=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);t&&this._linkAtPosition(e.link,t)&&(this._currentLink=e,this._currentLink.state={decorations:{underline:void 0===e.link.decorations||e.link.decorations.underline,pointerCursor:void 0===e.link.decorations||e.link.decorations.pointerCursor},isHovered:!0},this._linkHover(this._element,e.link,this._lastMouseEvent),e.link.decorations={},Object.defineProperties(e.link.decorations,{pointerCursor:{get:()=>{var e,t;return null===(t=null===(e=this._currentLink)||void 0===e?void 0:e.state)||void 0===t?void 0:t.decorations.pointerCursor},set:e=>{var t,i;(null===(t=this._currentLink)||void 0===t?void 0:t.state)&&this._currentLink.state.decorations.pointerCursor!==e&&(this._currentLink.state.decorations.pointerCursor=e,this._currentLink.state.isHovered&&(null===(i=this._element)||void 0===i||i.classList.toggle("xterm-cursor-pointer",e)))}},underline:{get:()=>{var e,t;return null===(t=null===(e=this._currentLink)||void 0===e?void 0:e.state)||void 0===t?void 0:t.decorations.underline},set:t=>{var i,s,r;(null===(i=this._currentLink)||void 0===i?void 0:i.state)&&(null===(r=null===(s=this._currentLink)||void 0===s?void 0:s.state)||void 0===r?void 0:r.decorations.underline)!==t&&(this._currentLink.state.decorations.underline=t,this._currentLink.state.isHovered&&this._fireUnderlineEvent(e.link,t))}}}),this._renderService&&this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange((e=>{if(!this._currentLink)return;const t=0===e.start?0:e.start+1+this._bufferService.buffer.ydisp,i=this._bufferService.buffer.ydisp+1+e.end;if(this._currentLink.link.range.start.y>=t&&this._currentLink.link.range.end.y<=i&&(this._clearCurrentLink(t,i),this._lastMouseEvent&&this._element)){const e=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);e&&this._askForLink(e,!1)}}))))}_linkHover(e,t,i){var s;(null===(s=this._currentLink)||void 0===s?void 0:s.state)&&(this._currentLink.state.isHovered=!0,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(t,!0),this._currentLink.state.decorations.pointerCursor&&e.classList.add("xterm-cursor-pointer")),t.hover&&t.hover(i,t.text)}_fireUnderlineEvent(e,t){const i=e.range,s=this._bufferService.buffer.ydisp,r=this._createLinkUnderlineEvent(i.start.x-1,i.start.y-s-1,i.end.x,i.end.y-s-1,void 0);(t?this._onShowLinkUnderline:this._onHideLinkUnderline).fire(r)}_linkLeave(e,t,i){var s;(null===(s=this._currentLink)||void 0===s?void 0:s.state)&&(this._currentLink.state.isHovered=!1,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(t,!1),this._currentLink.state.decorations.pointerCursor&&e.classList.remove("xterm-cursor-pointer")),t.leave&&t.leave(i,t.text)}_linkAtPosition(e,t){const i=e.range.start.y*this._bufferService.cols+e.range.start.x,s=e.range.end.y*this._bufferService.cols+e.range.end.x,r=t.y*this._bufferService.cols+t.x;return i<=r&&r<=s}_positionFromMouseEvent(e,t,i){const s=i.getCoords(e,t,this._bufferService.cols,this._bufferService.rows);if(s)return{x:s[0],y:s[1]+this._bufferService.buffer.ydisp}}_createLinkUnderlineEvent(e,t,i,s,r){return{x1:e,y1:t,x2:i,y2:s,cols:this._bufferService.cols,fg:r}}};t.Linkifier2=c=s([r(0,h.IBufferService)],c)},9042:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.tooMuchOutput=t.promptLabel=void 0,t.promptLabel="Terminal input",t.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},3730:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkProvider=void 0;const n=i(511),o=i(2585);let a=t.OscLinkProvider=class{constructor(e,t,i){this._bufferService=e,this._optionsService=t,this._oscLinkService=i}provideLinks(e,t){var i;const s=this._bufferService.buffer.lines.get(e-1);if(!s)return void t(void 0);const r=[],o=this._optionsService.rawOptions.linkHandler,a=new n.CellData,c=s.getTrimmedLength();let l=-1,d=-1,_=!1;for(let t=0;to?o.activate(e,t,i):h(0,t),hover:(e,t)=>{var s;return null===(s=null==o?void 0:o.hover)||void 0===s?void 0:s.call(o,e,t,i)},leave:(e,t)=>{var s;return null===(s=null==o?void 0:o.leave)||void 0===s?void 0:s.call(o,e,t,i)}})}_=!1,a.hasExtendedAttrs()&&a.extended.urlId?(d=t,l=a.extended.urlId):(d=-1,l=-1)}}t(r)}};function h(e,t){if(confirm(`Do you want to navigate to ${t}?\n\nWARNING: This link could potentially be dangerous`)){const e=window.open();if(e){try{e.opener=null}catch(e){}e.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}}t.OscLinkProvider=a=s([r(0,o.IBufferService),r(1,o.IOptionsService),r(2,o.IOscLinkService)],a)},6193:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.RenderDebouncer=void 0,t.RenderDebouncer=class{constructor(e,t){this._parentWindow=e,this._renderCallback=t,this._refreshCallbacks=[]}dispose(){this._animationFrame&&(this._parentWindow.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)}addRefreshCallback(e){return this._refreshCallbacks.push(e),this._animationFrame||(this._animationFrame=this._parentWindow.requestAnimationFrame((()=>this._innerRefresh()))),this._animationFrame}refresh(e,t,i){this._rowCount=i,e=void 0!==e?e:0,t=void 0!==t?t:this._rowCount-1,this._rowStart=void 0!==this._rowStart?Math.min(this._rowStart,e):e,this._rowEnd=void 0!==this._rowEnd?Math.max(this._rowEnd,t):t,this._animationFrame||(this._animationFrame=this._parentWindow.requestAnimationFrame((()=>this._innerRefresh())))}_innerRefresh(){if(this._animationFrame=void 0,void 0===this._rowStart||void 0===this._rowEnd||void 0===this._rowCount)return void this._runRefreshCallbacks();const e=Math.max(this._rowStart,0),t=Math.min(this._rowEnd,this._rowCount-1);this._rowStart=void 0,this._rowEnd=void 0,this._renderCallback(e,t),this._runRefreshCallbacks()}_runRefreshCallbacks(){for(const e of this._refreshCallbacks)e(0);this._refreshCallbacks=[]}}},5596:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ScreenDprMonitor=void 0;const s=i(844);class r extends s.Disposable{constructor(e){super(),this._parentWindow=e,this._currentDevicePixelRatio=this._parentWindow.devicePixelRatio,this.register((0,s.toDisposable)((()=>{this.clearListener()})))}setListener(e){this._listener&&this.clearListener(),this._listener=e,this._outerListener=()=>{this._listener&&(this._listener(this._parentWindow.devicePixelRatio,this._currentDevicePixelRatio),this._updateDpr())},this._updateDpr()}_updateDpr(){var e;this._outerListener&&(null===(e=this._resolutionMediaMatchList)||void 0===e||e.removeListener(this._outerListener),this._currentDevicePixelRatio=this._parentWindow.devicePixelRatio,this._resolutionMediaMatchList=this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`),this._resolutionMediaMatchList.addListener(this._outerListener))}clearListener(){this._resolutionMediaMatchList&&this._listener&&this._outerListener&&(this._resolutionMediaMatchList.removeListener(this._outerListener),this._resolutionMediaMatchList=void 0,this._listener=void 0,this._outerListener=void 0)}}t.ScreenDprMonitor=r},3236:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Terminal=void 0;const s=i(3614),r=i(3656),n=i(6465),o=i(9042),a=i(3730),h=i(1680),c=i(3107),l=i(5744),d=i(2950),_=i(1296),u=i(428),f=i(4269),v=i(5114),p=i(8934),g=i(3230),m=i(9312),S=i(4725),C=i(6731),b=i(8055),y=i(8969),w=i(8460),E=i(844),k=i(6114),L=i(8437),D=i(2584),R=i(7399),x=i(5941),A=i(9074),B=i(2585),T=i(5435),M=i(4567),O="undefined"!=typeof window?window.document:null;class P extends y.CoreTerminal{get onFocus(){return this._onFocus.event}get onBlur(){return this._onBlur.event}get onA11yChar(){return this._onA11yCharEmitter.event}get onA11yTab(){return this._onA11yTabEmitter.event}get onWillOpen(){return this._onWillOpen.event}constructor(e={}){super(e),this.browser=k,this._keyDownHandled=!1,this._keyDownSeen=!1,this._keyPressHandled=!1,this._unprocessedDeadKey=!1,this._accessibilityManager=this.register(new E.MutableDisposable),this._onCursorMove=this.register(new w.EventEmitter),this.onCursorMove=this._onCursorMove.event,this._onKey=this.register(new w.EventEmitter),this.onKey=this._onKey.event,this._onRender=this.register(new w.EventEmitter),this.onRender=this._onRender.event,this._onSelectionChange=this.register(new w.EventEmitter),this.onSelectionChange=this._onSelectionChange.event,this._onTitleChange=this.register(new w.EventEmitter),this.onTitleChange=this._onTitleChange.event,this._onBell=this.register(new w.EventEmitter),this.onBell=this._onBell.event,this._onFocus=this.register(new w.EventEmitter),this._onBlur=this.register(new w.EventEmitter),this._onA11yCharEmitter=this.register(new w.EventEmitter),this._onA11yTabEmitter=this.register(new w.EventEmitter),this._onWillOpen=this.register(new w.EventEmitter),this._setup(),this.linkifier2=this.register(this._instantiationService.createInstance(n.Linkifier2)),this.linkifier2.registerLinkProvider(this._instantiationService.createInstance(a.OscLinkProvider)),this._decorationService=this._instantiationService.createInstance(A.DecorationService),this._instantiationService.setService(B.IDecorationService,this._decorationService),this.register(this._inputHandler.onRequestBell((()=>this._onBell.fire()))),this.register(this._inputHandler.onRequestRefreshRows(((e,t)=>this.refresh(e,t)))),this.register(this._inputHandler.onRequestSendFocus((()=>this._reportFocus()))),this.register(this._inputHandler.onRequestReset((()=>this.reset()))),this.register(this._inputHandler.onRequestWindowsOptionsReport((e=>this._reportWindowsOptions(e)))),this.register(this._inputHandler.onColor((e=>this._handleColorEvent(e)))),this.register((0,w.forwardEvent)(this._inputHandler.onCursorMove,this._onCursorMove)),this.register((0,w.forwardEvent)(this._inputHandler.onTitleChange,this._onTitleChange)),this.register((0,w.forwardEvent)(this._inputHandler.onA11yChar,this._onA11yCharEmitter)),this.register((0,w.forwardEvent)(this._inputHandler.onA11yTab,this._onA11yTabEmitter)),this.register(this._bufferService.onResize((e=>this._afterResize(e.cols,e.rows)))),this.register((0,E.toDisposable)((()=>{var e,t;this._customKeyEventHandler=void 0,null===(t=null===(e=this.element)||void 0===e?void 0:e.parentNode)||void 0===t||t.removeChild(this.element)})))}_handleColorEvent(e){if(this._themeService)for(const t of e){let e,i="";switch(t.index){case 256:e="foreground",i="10";break;case 257:e="background",i="11";break;case 258:e="cursor",i="12";break;default:e="ansi",i="4;"+t.index}switch(t.type){case 0:const s=b.color.toColorRGB("ansi"===e?this._themeService.colors.ansi[t.index]:this._themeService.colors[e]);this.coreService.triggerDataEvent(`${D.C0.ESC}]${i};${(0,x.toRgbString)(s)}${D.C1_ESCAPED.ST}`);break;case 1:if("ansi"===e)this._themeService.modifyColors((e=>e.ansi[t.index]=b.rgba.toColor(...t.color)));else{const i=e;this._themeService.modifyColors((e=>e[i]=b.rgba.toColor(...t.color)))}break;case 2:this._themeService.restoreColor(t.index)}}}_setup(){super._setup(),this._customKeyEventHandler=void 0}get buffer(){return this.buffers.active}focus(){this.textarea&&this.textarea.focus({preventScroll:!0})}_handleScreenReaderModeOptionChange(e){e?!this._accessibilityManager.value&&this._renderService&&(this._accessibilityManager.value=this._instantiationService.createInstance(M.AccessibilityManager,this)):this._accessibilityManager.clear()}_handleTextAreaFocus(e){this.coreService.decPrivateModes.sendFocus&&this.coreService.triggerDataEvent(D.C0.ESC+"[I"),this.updateCursorStyle(e),this.element.classList.add("focus"),this._showCursor(),this._onFocus.fire()}blur(){var e;return null===(e=this.textarea)||void 0===e?void 0:e.blur()}_handleTextAreaBlur(){this.textarea.value="",this.refresh(this.buffer.y,this.buffer.y),this.coreService.decPrivateModes.sendFocus&&this.coreService.triggerDataEvent(D.C0.ESC+"[O"),this.element.classList.remove("focus"),this._onBlur.fire()}_syncTextArea(){if(!this.textarea||!this.buffer.isCursorInViewport||this._compositionHelper.isComposing||!this._renderService)return;const e=this.buffer.ybase+this.buffer.y,t=this.buffer.lines.get(e);if(!t)return;const i=Math.min(this.buffer.x,this.cols-1),s=this._renderService.dimensions.css.cell.height,r=t.getWidth(i),n=this._renderService.dimensions.css.cell.width*r,o=this.buffer.y*this._renderService.dimensions.css.cell.height,a=i*this._renderService.dimensions.css.cell.width;this.textarea.style.left=a+"px",this.textarea.style.top=o+"px",this.textarea.style.width=n+"px",this.textarea.style.height=s+"px",this.textarea.style.lineHeight=s+"px",this.textarea.style.zIndex="-5"}_initGlobal(){this._bindKeys(),this.register((0,r.addDisposableDomListener)(this.element,"copy",(e=>{this.hasSelection()&&(0,s.copyHandler)(e,this._selectionService)})));const e=e=>(0,s.handlePasteEvent)(e,this.textarea,this.coreService,this.optionsService);this.register((0,r.addDisposableDomListener)(this.textarea,"paste",e)),this.register((0,r.addDisposableDomListener)(this.element,"paste",e)),k.isFirefox?this.register((0,r.addDisposableDomListener)(this.element,"mousedown",(e=>{2===e.button&&(0,s.rightClickHandler)(e,this.textarea,this.screenElement,this._selectionService,this.options.rightClickSelectsWord)}))):this.register((0,r.addDisposableDomListener)(this.element,"contextmenu",(e=>{(0,s.rightClickHandler)(e,this.textarea,this.screenElement,this._selectionService,this.options.rightClickSelectsWord)}))),k.isLinux&&this.register((0,r.addDisposableDomListener)(this.element,"auxclick",(e=>{1===e.button&&(0,s.moveTextAreaUnderMouseCursor)(e,this.textarea,this.screenElement)})))}_bindKeys(){this.register((0,r.addDisposableDomListener)(this.textarea,"keyup",(e=>this._keyUp(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"keydown",(e=>this._keyDown(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"keypress",(e=>this._keyPress(e)),!0)),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionstart",(()=>this._compositionHelper.compositionstart()))),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionupdate",(e=>this._compositionHelper.compositionupdate(e)))),this.register((0,r.addDisposableDomListener)(this.textarea,"compositionend",(()=>this._compositionHelper.compositionend()))),this.register((0,r.addDisposableDomListener)(this.textarea,"input",(e=>this._inputEvent(e)),!0)),this.register(this.onRender((()=>this._compositionHelper.updateCompositionElements())))}open(e){var t;if(!e)throw new Error("Terminal requires a parent element.");e.isConnected||this._logService.debug("Terminal.open was called on an element that was not attached to the DOM"),this._document=e.ownerDocument,this.element=this._document.createElement("div"),this.element.dir="ltr",this.element.classList.add("terminal"),this.element.classList.add("xterm"),e.appendChild(this.element);const i=O.createDocumentFragment();this._viewportElement=O.createElement("div"),this._viewportElement.classList.add("xterm-viewport"),i.appendChild(this._viewportElement),this._viewportScrollArea=O.createElement("div"),this._viewportScrollArea.classList.add("xterm-scroll-area"),this._viewportElement.appendChild(this._viewportScrollArea),this.screenElement=O.createElement("div"),this.screenElement.classList.add("xterm-screen"),this._helperContainer=O.createElement("div"),this._helperContainer.classList.add("xterm-helpers"),this.screenElement.appendChild(this._helperContainer),i.appendChild(this.screenElement),this.textarea=O.createElement("textarea"),this.textarea.classList.add("xterm-helper-textarea"),this.textarea.setAttribute("aria-label",o.promptLabel),k.isChromeOS||this.textarea.setAttribute("aria-multiline","false"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.tabIndex=0,this._coreBrowserService=this._instantiationService.createInstance(v.CoreBrowserService,this.textarea,null!==(t=this._document.defaultView)&&void 0!==t?t:window),this._instantiationService.setService(S.ICoreBrowserService,this._coreBrowserService),this.register((0,r.addDisposableDomListener)(this.textarea,"focus",(e=>this._handleTextAreaFocus(e)))),this.register((0,r.addDisposableDomListener)(this.textarea,"blur",(()=>this._handleTextAreaBlur()))),this._helperContainer.appendChild(this.textarea),this._charSizeService=this._instantiationService.createInstance(u.CharSizeService,this._document,this._helperContainer),this._instantiationService.setService(S.ICharSizeService,this._charSizeService),this._themeService=this._instantiationService.createInstance(C.ThemeService),this._instantiationService.setService(S.IThemeService,this._themeService),this._characterJoinerService=this._instantiationService.createInstance(f.CharacterJoinerService),this._instantiationService.setService(S.ICharacterJoinerService,this._characterJoinerService),this._renderService=this.register(this._instantiationService.createInstance(g.RenderService,this.rows,this.screenElement)),this._instantiationService.setService(S.IRenderService,this._renderService),this.register(this._renderService.onRenderedViewportChange((e=>this._onRender.fire(e)))),this.onResize((e=>this._renderService.resize(e.cols,e.rows))),this._compositionView=O.createElement("div"),this._compositionView.classList.add("composition-view"),this._compositionHelper=this._instantiationService.createInstance(d.CompositionHelper,this.textarea,this._compositionView),this._helperContainer.appendChild(this._compositionView),this.element.appendChild(i);try{this._onWillOpen.fire(this.element)}catch(e){}this._renderService.hasRenderer()||this._renderService.setRenderer(this._createRenderer()),this._mouseService=this._instantiationService.createInstance(p.MouseService),this._instantiationService.setService(S.IMouseService,this._mouseService),this.viewport=this._instantiationService.createInstance(h.Viewport,this._viewportElement,this._viewportScrollArea),this.viewport.onRequestScrollLines((e=>this.scrollLines(e.amount,e.suppressScrollEvent,1))),this.register(this._inputHandler.onRequestSyncScrollBar((()=>this.viewport.syncScrollArea()))),this.register(this.viewport),this.register(this.onCursorMove((()=>{this._renderService.handleCursorMove(),this._syncTextArea()}))),this.register(this.onResize((()=>this._renderService.handleResize(this.cols,this.rows)))),this.register(this.onBlur((()=>this._renderService.handleBlur()))),this.register(this.onFocus((()=>this._renderService.handleFocus()))),this.register(this._renderService.onDimensionsChange((()=>this.viewport.syncScrollArea()))),this._selectionService=this.register(this._instantiationService.createInstance(m.SelectionService,this.element,this.screenElement,this.linkifier2)),this._instantiationService.setService(S.ISelectionService,this._selectionService),this.register(this._selectionService.onRequestScrollLines((e=>this.scrollLines(e.amount,e.suppressScrollEvent)))),this.register(this._selectionService.onSelectionChange((()=>this._onSelectionChange.fire()))),this.register(this._selectionService.onRequestRedraw((e=>this._renderService.handleSelectionChanged(e.start,e.end,e.columnSelectMode)))),this.register(this._selectionService.onLinuxMouseSelection((e=>{this.textarea.value=e,this.textarea.focus(),this.textarea.select()}))),this.register(this._onScroll.event((e=>{this.viewport.syncScrollArea(),this._selectionService.refresh()}))),this.register((0,r.addDisposableDomListener)(this._viewportElement,"scroll",(()=>this._selectionService.refresh()))),this.linkifier2.attachToDom(this.screenElement,this._mouseService,this._renderService),this.register(this._instantiationService.createInstance(c.BufferDecorationRenderer,this.screenElement)),this.register((0,r.addDisposableDomListener)(this.element,"mousedown",(e=>this._selectionService.handleMouseDown(e)))),this.coreMouseService.areMouseEventsActive?(this._selectionService.disable(),this.element.classList.add("enable-mouse-events")):this._selectionService.enable(),this.options.screenReaderMode&&(this._accessibilityManager.value=this._instantiationService.createInstance(M.AccessibilityManager,this)),this.register(this.optionsService.onSpecificOptionChange("screenReaderMode",(e=>this._handleScreenReaderModeOptionChange(e)))),this.options.overviewRulerWidth&&(this._overviewRulerRenderer=this.register(this._instantiationService.createInstance(l.OverviewRulerRenderer,this._viewportElement,this.screenElement))),this.optionsService.onSpecificOptionChange("overviewRulerWidth",(e=>{!this._overviewRulerRenderer&&e&&this._viewportElement&&this.screenElement&&(this._overviewRulerRenderer=this.register(this._instantiationService.createInstance(l.OverviewRulerRenderer,this._viewportElement,this.screenElement)))})),this._charSizeService.measure(),this.refresh(0,this.rows-1),this._initGlobal(),this.bindMouse()}_createRenderer(){return this._instantiationService.createInstance(_.DomRenderer,this.element,this.screenElement,this._viewportElement,this.linkifier2)}bindMouse(){const e=this,t=this.element;function i(t){const i=e._mouseService.getMouseReportCoords(t,e.screenElement);if(!i)return!1;let s,r;switch(t.overrideType||t.type){case"mousemove":r=32,void 0===t.buttons?(s=3,void 0!==t.button&&(s=t.button<3?t.button:3)):s=1&t.buttons?0:4&t.buttons?1:2&t.buttons?2:3;break;case"mouseup":r=0,s=t.button<3?t.button:3;break;case"mousedown":r=1,s=t.button<3?t.button:3;break;case"wheel":if(0===e.viewport.getLinesScrolled(t))return!1;r=t.deltaY<0?0:1,s=4;break;default:return!1}return!(void 0===r||void 0===s||s>4)&&e.coreMouseService.triggerMouseEvent({col:i.col,row:i.row,x:i.x,y:i.y,button:s,action:r,ctrl:t.ctrlKey,alt:t.altKey,shift:t.shiftKey})}const s={mouseup:null,wheel:null,mousedrag:null,mousemove:null},n={mouseup:e=>(i(e),e.buttons||(this._document.removeEventListener("mouseup",s.mouseup),s.mousedrag&&this._document.removeEventListener("mousemove",s.mousedrag)),this.cancel(e)),wheel:e=>(i(e),this.cancel(e,!0)),mousedrag:e=>{e.buttons&&i(e)},mousemove:e=>{e.buttons||i(e)}};this.register(this.coreMouseService.onProtocolChange((e=>{e?("debug"===this.optionsService.rawOptions.logLevel&&this._logService.debug("Binding to mouse events:",this.coreMouseService.explainEvents(e)),this.element.classList.add("enable-mouse-events"),this._selectionService.disable()):(this._logService.debug("Unbinding from mouse events."),this.element.classList.remove("enable-mouse-events"),this._selectionService.enable()),8&e?s.mousemove||(t.addEventListener("mousemove",n.mousemove),s.mousemove=n.mousemove):(t.removeEventListener("mousemove",s.mousemove),s.mousemove=null),16&e?s.wheel||(t.addEventListener("wheel",n.wheel,{passive:!1}),s.wheel=n.wheel):(t.removeEventListener("wheel",s.wheel),s.wheel=null),2&e?s.mouseup||(t.addEventListener("mouseup",n.mouseup),s.mouseup=n.mouseup):(this._document.removeEventListener("mouseup",s.mouseup),t.removeEventListener("mouseup",s.mouseup),s.mouseup=null),4&e?s.mousedrag||(s.mousedrag=n.mousedrag):(this._document.removeEventListener("mousemove",s.mousedrag),s.mousedrag=null)}))),this.coreMouseService.activeProtocol=this.coreMouseService.activeProtocol,this.register((0,r.addDisposableDomListener)(t,"mousedown",(e=>{if(e.preventDefault(),this.focus(),this.coreMouseService.areMouseEventsActive&&!this._selectionService.shouldForceSelection(e))return i(e),s.mouseup&&this._document.addEventListener("mouseup",s.mouseup),s.mousedrag&&this._document.addEventListener("mousemove",s.mousedrag),this.cancel(e)}))),this.register((0,r.addDisposableDomListener)(t,"wheel",(e=>{if(!s.wheel){if(!this.buffer.hasScrollback){const t=this.viewport.getLinesScrolled(e);if(0===t)return;const i=D.C0.ESC+(this.coreService.decPrivateModes.applicationCursorKeys?"O":"[")+(e.deltaY<0?"A":"B");let s="";for(let e=0;e{if(!this.coreMouseService.areMouseEventsActive)return this.viewport.handleTouchStart(e),this.cancel(e)}),{passive:!0})),this.register((0,r.addDisposableDomListener)(t,"touchmove",(e=>{if(!this.coreMouseService.areMouseEventsActive)return this.viewport.handleTouchMove(e)?void 0:this.cancel(e)}),{passive:!1}))}refresh(e,t){var i;null===(i=this._renderService)||void 0===i||i.refreshRows(e,t)}updateCursorStyle(e){var t;(null===(t=this._selectionService)||void 0===t?void 0:t.shouldColumnSelect(e))?this.element.classList.add("column-select"):this.element.classList.remove("column-select")}_showCursor(){this.coreService.isCursorInitialized||(this.coreService.isCursorInitialized=!0,this.refresh(this.buffer.y,this.buffer.y))}scrollLines(e,t,i=0){var s;1===i?(super.scrollLines(e,t,i),this.refresh(0,this.rows-1)):null===(s=this.viewport)||void 0===s||s.scrollLines(e)}paste(e){(0,s.paste)(e,this.textarea,this.coreService,this.optionsService)}attachCustomKeyEventHandler(e){this._customKeyEventHandler=e}registerLinkProvider(e){return this.linkifier2.registerLinkProvider(e)}registerCharacterJoiner(e){if(!this._characterJoinerService)throw new Error("Terminal must be opened first");const t=this._characterJoinerService.register(e);return this.refresh(0,this.rows-1),t}deregisterCharacterJoiner(e){if(!this._characterJoinerService)throw new Error("Terminal must be opened first");this._characterJoinerService.deregister(e)&&this.refresh(0,this.rows-1)}get markers(){return this.buffer.markers}registerMarker(e){return this.buffer.addMarker(this.buffer.ybase+this.buffer.y+e)}registerDecoration(e){return this._decorationService.registerDecoration(e)}hasSelection(){return!!this._selectionService&&this._selectionService.hasSelection}select(e,t,i){this._selectionService.setSelection(e,t,i)}getSelection(){return this._selectionService?this._selectionService.selectionText:""}getSelectionPosition(){if(this._selectionService&&this._selectionService.hasSelection)return{start:{x:this._selectionService.selectionStart[0],y:this._selectionService.selectionStart[1]},end:{x:this._selectionService.selectionEnd[0],y:this._selectionService.selectionEnd[1]}}}clearSelection(){var e;null===(e=this._selectionService)||void 0===e||e.clearSelection()}selectAll(){var e;null===(e=this._selectionService)||void 0===e||e.selectAll()}selectLines(e,t){var i;null===(i=this._selectionService)||void 0===i||i.selectLines(e,t)}_keyDown(e){if(this._keyDownHandled=!1,this._keyDownSeen=!0,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;const t=this.browser.isMac&&this.options.macOptionIsMeta&&e.altKey;if(!t&&!this._compositionHelper.keydown(e))return this.options.scrollOnUserInput&&this.buffer.ybase!==this.buffer.ydisp&&this.scrollToBottom(),!1;t||"Dead"!==e.key&&"AltGraph"!==e.key||(this._unprocessedDeadKey=!0);const i=(0,R.evaluateKeyboardEvent)(e,this.coreService.decPrivateModes.applicationCursorKeys,this.browser.isMac,this.options.macOptionIsMeta);if(this.updateCursorStyle(e),3===i.type||2===i.type){const t=this.rows-1;return this.scrollLines(2===i.type?-t:t),this.cancel(e,!0)}return 1===i.type&&this.selectAll(),!!this._isThirdLevelShift(this.browser,e)||(i.cancel&&this.cancel(e,!0),!i.key||!!(e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&1===e.key.length&&e.key.charCodeAt(0)>=65&&e.key.charCodeAt(0)<=90)||(this._unprocessedDeadKey?(this._unprocessedDeadKey=!1,!0):(i.key!==D.C0.ETX&&i.key!==D.C0.CR||(this.textarea.value=""),this._onKey.fire({key:i.key,domEvent:e}),this._showCursor(),this.coreService.triggerDataEvent(i.key,!0),!this.optionsService.rawOptions.screenReaderMode||e.altKey||e.ctrlKey?this.cancel(e,!0):void(this._keyDownHandled=!0))))}_isThirdLevelShift(e,t){const i=e.isMac&&!this.options.macOptionIsMeta&&t.altKey&&!t.ctrlKey&&!t.metaKey||e.isWindows&&t.altKey&&t.ctrlKey&&!t.metaKey||e.isWindows&&t.getModifierState("AltGraph");return"keypress"===t.type?i:i&&(!t.keyCode||t.keyCode>47)}_keyUp(e){this._keyDownSeen=!1,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e)||(function(e){return 16===e.keyCode||17===e.keyCode||18===e.keyCode}(e)||this.focus(),this.updateCursorStyle(e),this._keyPressHandled=!1)}_keyPress(e){let t;if(this._keyPressHandled=!1,this._keyDownHandled)return!1;if(this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(this.cancel(e),e.charCode)t=e.charCode;else if(null===e.which||void 0===e.which)t=e.keyCode;else{if(0===e.which||0===e.charCode)return!1;t=e.which}return!(!t||(e.altKey||e.ctrlKey||e.metaKey)&&!this._isThirdLevelShift(this.browser,e)||(t=String.fromCharCode(t),this._onKey.fire({key:t,domEvent:e}),this._showCursor(),this.coreService.triggerDataEvent(t,!0),this._keyPressHandled=!0,this._unprocessedDeadKey=!1,0))}_inputEvent(e){if(e.data&&"insertText"===e.inputType&&(!e.composed||!this._keyDownSeen)&&!this.optionsService.rawOptions.screenReaderMode){if(this._keyPressHandled)return!1;this._unprocessedDeadKey=!1;const t=e.data;return this.coreService.triggerDataEvent(t,!0),this.cancel(e),!0}return!1}resize(e,t){e!==this.cols||t!==this.rows?super.resize(e,t):this._charSizeService&&!this._charSizeService.hasValidSize&&this._charSizeService.measure()}_afterResize(e,t){var i,s;null===(i=this._charSizeService)||void 0===i||i.measure(),null===(s=this.viewport)||void 0===s||s.syncScrollArea(!0)}clear(){var e;if(0!==this.buffer.ybase||0!==this.buffer.y){this.buffer.clearAllMarkers(),this.buffer.lines.set(0,this.buffer.lines.get(this.buffer.ybase+this.buffer.y)),this.buffer.lines.length=1,this.buffer.ydisp=0,this.buffer.ybase=0,this.buffer.y=0;for(let e=1;e{Object.defineProperty(t,"__esModule",{value:!0}),t.TimeBasedDebouncer=void 0,t.TimeBasedDebouncer=class{constructor(e,t=1e3){this._renderCallback=e,this._debounceThresholdMS=t,this._lastRefreshMs=0,this._additionalRefreshRequested=!1}dispose(){this._refreshTimeoutID&&clearTimeout(this._refreshTimeoutID)}refresh(e,t,i){this._rowCount=i,e=void 0!==e?e:0,t=void 0!==t?t:this._rowCount-1,this._rowStart=void 0!==this._rowStart?Math.min(this._rowStart,e):e,this._rowEnd=void 0!==this._rowEnd?Math.max(this._rowEnd,t):t;const s=Date.now();if(s-this._lastRefreshMs>=this._debounceThresholdMS)this._lastRefreshMs=s,this._innerRefresh();else if(!this._additionalRefreshRequested){const e=s-this._lastRefreshMs,t=this._debounceThresholdMS-e;this._additionalRefreshRequested=!0,this._refreshTimeoutID=window.setTimeout((()=>{this._lastRefreshMs=Date.now(),this._innerRefresh(),this._additionalRefreshRequested=!1,this._refreshTimeoutID=void 0}),t)}}_innerRefresh(){if(void 0===this._rowStart||void 0===this._rowEnd||void 0===this._rowCount)return;const e=Math.max(this._rowStart,0),t=Math.min(this._rowEnd,this._rowCount-1);this._rowStart=void 0,this._rowEnd=void 0,this._renderCallback(e,t)}}},1680:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.Viewport=void 0;const n=i(3656),o=i(4725),a=i(8460),h=i(844),c=i(2585);let l=t.Viewport=class extends h.Disposable{constructor(e,t,i,s,r,o,h,c){super(),this._viewportElement=e,this._scrollArea=t,this._bufferService=i,this._optionsService=s,this._charSizeService=r,this._renderService=o,this._coreBrowserService=h,this.scrollBarWidth=0,this._currentRowHeight=0,this._currentDeviceCellHeight=0,this._lastRecordedBufferLength=0,this._lastRecordedViewportHeight=0,this._lastRecordedBufferHeight=0,this._lastTouchY=0,this._lastScrollTop=0,this._wheelPartialScroll=0,this._refreshAnimationFrame=null,this._ignoreNextScrollEvent=!1,this._smoothScrollState={startTime:0,origin:-1,target:-1},this._onRequestScrollLines=this.register(new a.EventEmitter),this.onRequestScrollLines=this._onRequestScrollLines.event,this.scrollBarWidth=this._viewportElement.offsetWidth-this._scrollArea.offsetWidth||15,this.register((0,n.addDisposableDomListener)(this._viewportElement,"scroll",this._handleScroll.bind(this))),this._activeBuffer=this._bufferService.buffer,this.register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._renderDimensions=this._renderService.dimensions,this.register(this._renderService.onDimensionsChange((e=>this._renderDimensions=e))),this._handleThemeChange(c.colors),this.register(c.onChangeColors((e=>this._handleThemeChange(e)))),this.register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.syncScrollArea()))),setTimeout((()=>this.syncScrollArea()))}_handleThemeChange(e){this._viewportElement.style.backgroundColor=e.background.css}reset(){this._currentRowHeight=0,this._currentDeviceCellHeight=0,this._lastRecordedBufferLength=0,this._lastRecordedViewportHeight=0,this._lastRecordedBufferHeight=0,this._lastTouchY=0,this._lastScrollTop=0,this._coreBrowserService.window.requestAnimationFrame((()=>this.syncScrollArea()))}_refresh(e){if(e)return this._innerRefresh(),void(null!==this._refreshAnimationFrame&&this._coreBrowserService.window.cancelAnimationFrame(this._refreshAnimationFrame));null===this._refreshAnimationFrame&&(this._refreshAnimationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._innerRefresh())))}_innerRefresh(){if(this._charSizeService.height>0){this._currentRowHeight=this._renderService.dimensions.device.cell.height/this._coreBrowserService.dpr,this._currentDeviceCellHeight=this._renderService.dimensions.device.cell.height,this._lastRecordedViewportHeight=this._viewportElement.offsetHeight;const e=Math.round(this._currentRowHeight*this._lastRecordedBufferLength)+(this._lastRecordedViewportHeight-this._renderService.dimensions.css.canvas.height);this._lastRecordedBufferHeight!==e&&(this._lastRecordedBufferHeight=e,this._scrollArea.style.height=this._lastRecordedBufferHeight+"px")}const e=this._bufferService.buffer.ydisp*this._currentRowHeight;this._viewportElement.scrollTop!==e&&(this._ignoreNextScrollEvent=!0,this._viewportElement.scrollTop=e),this._refreshAnimationFrame=null}syncScrollArea(e=!1){if(this._lastRecordedBufferLength!==this._bufferService.buffer.lines.length)return this._lastRecordedBufferLength=this._bufferService.buffer.lines.length,void this._refresh(e);this._lastRecordedViewportHeight===this._renderService.dimensions.css.canvas.height&&this._lastScrollTop===this._activeBuffer.ydisp*this._currentRowHeight&&this._renderDimensions.device.cell.height===this._currentDeviceCellHeight||this._refresh(e)}_handleScroll(e){if(this._lastScrollTop=this._viewportElement.scrollTop,!this._viewportElement.offsetParent)return;if(this._ignoreNextScrollEvent)return this._ignoreNextScrollEvent=!1,void this._onRequestScrollLines.fire({amount:0,suppressScrollEvent:!0});const t=Math.round(this._lastScrollTop/this._currentRowHeight)-this._bufferService.buffer.ydisp;this._onRequestScrollLines.fire({amount:t,suppressScrollEvent:!0})}_smoothScroll(){if(this._isDisposed||-1===this._smoothScrollState.origin||-1===this._smoothScrollState.target)return;const e=this._smoothScrollPercent();this._viewportElement.scrollTop=this._smoothScrollState.origin+Math.round(e*(this._smoothScrollState.target-this._smoothScrollState.origin)),e<1?this._coreBrowserService.window.requestAnimationFrame((()=>this._smoothScroll())):this._clearSmoothScrollState()}_smoothScrollPercent(){return this._optionsService.rawOptions.smoothScrollDuration&&this._smoothScrollState.startTime?Math.max(Math.min((Date.now()-this._smoothScrollState.startTime)/this._optionsService.rawOptions.smoothScrollDuration,1),0):1}_clearSmoothScrollState(){this._smoothScrollState.startTime=0,this._smoothScrollState.origin=-1,this._smoothScrollState.target=-1}_bubbleScroll(e,t){const i=this._viewportElement.scrollTop+this._lastRecordedViewportHeight;return!(t<0&&0!==this._viewportElement.scrollTop||t>0&&i0&&(s=e),r=""}}return{bufferElements:n,cursorElement:s}}getLinesScrolled(e){if(0===e.deltaY||e.shiftKey)return 0;let t=this._applyScrollModifier(e.deltaY,e);return e.deltaMode===WheelEvent.DOM_DELTA_PIXEL?(t/=this._currentRowHeight+0,this._wheelPartialScroll+=t,t=Math.floor(Math.abs(this._wheelPartialScroll))*(this._wheelPartialScroll>0?1:-1),this._wheelPartialScroll%=1):e.deltaMode===WheelEvent.DOM_DELTA_PAGE&&(t*=this._bufferService.rows),t}_applyScrollModifier(e,t){const i=this._optionsService.rawOptions.fastScrollModifier;return"alt"===i&&t.altKey||"ctrl"===i&&t.ctrlKey||"shift"===i&&t.shiftKey?e*this._optionsService.rawOptions.fastScrollSensitivity*this._optionsService.rawOptions.scrollSensitivity:e*this._optionsService.rawOptions.scrollSensitivity}handleTouchStart(e){this._lastTouchY=e.touches[0].pageY}handleTouchMove(e){const t=this._lastTouchY-e.touches[0].pageY;return this._lastTouchY=e.touches[0].pageY,0!==t&&(this._viewportElement.scrollTop+=t,this._bubbleScroll(e,t))}};t.Viewport=l=s([r(2,c.IBufferService),r(3,c.IOptionsService),r(4,o.ICharSizeService),r(5,o.IRenderService),r(6,o.ICoreBrowserService),r(7,o.IThemeService)],l)},3107:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferDecorationRenderer=void 0;const n=i(3656),o=i(4725),a=i(844),h=i(2585);let c=t.BufferDecorationRenderer=class extends a.Disposable{constructor(e,t,i,s){super(),this._screenElement=e,this._bufferService=t,this._decorationService=i,this._renderService=s,this._decorationElements=new Map,this._altBufferIsActive=!1,this._dimensionsChanged=!1,this._container=document.createElement("div"),this._container.classList.add("xterm-decoration-container"),this._screenElement.appendChild(this._container),this.register(this._renderService.onRenderedViewportChange((()=>this._doRefreshDecorations()))),this.register(this._renderService.onDimensionsChange((()=>{this._dimensionsChanged=!0,this._queueRefresh()}))),this.register((0,n.addDisposableDomListener)(window,"resize",(()=>this._queueRefresh()))),this.register(this._bufferService.buffers.onBufferActivate((()=>{this._altBufferIsActive=this._bufferService.buffer===this._bufferService.buffers.alt}))),this.register(this._decorationService.onDecorationRegistered((()=>this._queueRefresh()))),this.register(this._decorationService.onDecorationRemoved((e=>this._removeDecoration(e)))),this.register((0,a.toDisposable)((()=>{this._container.remove(),this._decorationElements.clear()})))}_queueRefresh(){void 0===this._animationFrame&&(this._animationFrame=this._renderService.addRefreshCallback((()=>{this._doRefreshDecorations(),this._animationFrame=void 0})))}_doRefreshDecorations(){for(const e of this._decorationService.decorations)this._renderDecoration(e);this._dimensionsChanged=!1}_renderDecoration(e){this._refreshStyle(e),this._dimensionsChanged&&this._refreshXPosition(e)}_createElement(e){var t,i;const s=document.createElement("div");s.classList.add("xterm-decoration"),s.classList.toggle("xterm-decoration-top-layer","top"===(null===(t=null==e?void 0:e.options)||void 0===t?void 0:t.layer)),s.style.width=`${Math.round((e.options.width||1)*this._renderService.dimensions.css.cell.width)}px`,s.style.height=(e.options.height||1)*this._renderService.dimensions.css.cell.height+"px",s.style.top=(e.marker.line-this._bufferService.buffers.active.ydisp)*this._renderService.dimensions.css.cell.height+"px",s.style.lineHeight=`${this._renderService.dimensions.css.cell.height}px`;const r=null!==(i=e.options.x)&&void 0!==i?i:0;return r&&r>this._bufferService.cols&&(s.style.display="none"),this._refreshXPosition(e,s),s}_refreshStyle(e){const t=e.marker.line-this._bufferService.buffers.active.ydisp;if(t<0||t>=this._bufferService.rows)e.element&&(e.element.style.display="none",e.onRenderEmitter.fire(e.element));else{let i=this._decorationElements.get(e);i||(i=this._createElement(e),e.element=i,this._decorationElements.set(e,i),this._container.appendChild(i),e.onDispose((()=>{this._decorationElements.delete(e),i.remove()}))),i.style.top=t*this._renderService.dimensions.css.cell.height+"px",i.style.display=this._altBufferIsActive?"none":"block",e.onRenderEmitter.fire(i)}}_refreshXPosition(e,t=e.element){var i;if(!t)return;const s=null!==(i=e.options.x)&&void 0!==i?i:0;"right"===(e.options.anchor||"left")?t.style.right=s?s*this._renderService.dimensions.css.cell.width+"px":"":t.style.left=s?s*this._renderService.dimensions.css.cell.width+"px":""}_removeDecoration(e){var t;null===(t=this._decorationElements.get(e))||void 0===t||t.remove(),this._decorationElements.delete(e),e.dispose()}};t.BufferDecorationRenderer=c=s([r(1,h.IBufferService),r(2,h.IDecorationService),r(3,o.IRenderService)],c)},5871:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ColorZoneStore=void 0,t.ColorZoneStore=class{constructor(){this._zones=[],this._zonePool=[],this._zonePoolIndex=0,this._linePadding={full:0,left:0,center:0,right:0}}get zones(){return this._zonePool.length=Math.min(this._zonePool.length,this._zones.length),this._zones}clear(){this._zones.length=0,this._zonePoolIndex=0}addDecoration(e){if(e.options.overviewRulerOptions){for(const t of this._zones)if(t.color===e.options.overviewRulerOptions.color&&t.position===e.options.overviewRulerOptions.position){if(this._lineIntersectsZone(t,e.marker.line))return;if(this._lineAdjacentToZone(t,e.marker.line,e.options.overviewRulerOptions.position))return void this._addLineToZone(t,e.marker.line)}if(this._zonePoolIndex=e.startBufferLine&&t<=e.endBufferLine}_lineAdjacentToZone(e,t,i){return t>=e.startBufferLine-this._linePadding[i||"full"]&&t<=e.endBufferLine+this._linePadding[i||"full"]}_addLineToZone(e,t){e.startBufferLine=Math.min(e.startBufferLine,t),e.endBufferLine=Math.max(e.endBufferLine,t)}}},5744:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OverviewRulerRenderer=void 0;const n=i(5871),o=i(3656),a=i(4725),h=i(844),c=i(2585),l={full:0,left:0,center:0,right:0},d={full:0,left:0,center:0,right:0},_={full:0,left:0,center:0,right:0};let u=t.OverviewRulerRenderer=class extends h.Disposable{get _width(){return this._optionsService.options.overviewRulerWidth||0}constructor(e,t,i,s,r,o,a){var c;super(),this._viewportElement=e,this._screenElement=t,this._bufferService=i,this._decorationService=s,this._renderService=r,this._optionsService=o,this._coreBrowseService=a,this._colorZoneStore=new n.ColorZoneStore,this._shouldUpdateDimensions=!0,this._shouldUpdateAnchor=!0,this._lastKnownBufferLength=0,this._canvas=document.createElement("canvas"),this._canvas.classList.add("xterm-decoration-overview-ruler"),this._refreshCanvasDimensions(),null===(c=this._viewportElement.parentElement)||void 0===c||c.insertBefore(this._canvas,this._viewportElement);const l=this._canvas.getContext("2d");if(!l)throw new Error("Ctx cannot be null");this._ctx=l,this._registerDecorationListeners(),this._registerBufferChangeListeners(),this._registerDimensionChangeListeners(),this.register((0,h.toDisposable)((()=>{var e;null===(e=this._canvas)||void 0===e||e.remove()})))}_registerDecorationListeners(){this.register(this._decorationService.onDecorationRegistered((()=>this._queueRefresh(void 0,!0)))),this.register(this._decorationService.onDecorationRemoved((()=>this._queueRefresh(void 0,!0))))}_registerBufferChangeListeners(){this.register(this._renderService.onRenderedViewportChange((()=>this._queueRefresh()))),this.register(this._bufferService.buffers.onBufferActivate((()=>{this._canvas.style.display=this._bufferService.buffer===this._bufferService.buffers.alt?"none":"block"}))),this.register(this._bufferService.onScroll((()=>{this._lastKnownBufferLength!==this._bufferService.buffers.normal.lines.length&&(this._refreshDrawHeightConstants(),this._refreshColorZonePadding())})))}_registerDimensionChangeListeners(){this.register(this._renderService.onRender((()=>{this._containerHeight&&this._containerHeight===this._screenElement.clientHeight||(this._queueRefresh(!0),this._containerHeight=this._screenElement.clientHeight)}))),this.register(this._optionsService.onSpecificOptionChange("overviewRulerWidth",(()=>this._queueRefresh(!0)))),this.register((0,o.addDisposableDomListener)(this._coreBrowseService.window,"resize",(()=>this._queueRefresh(!0)))),this._queueRefresh(!0)}_refreshDrawConstants(){const e=Math.floor(this._canvas.width/3),t=Math.ceil(this._canvas.width/3);d.full=this._canvas.width,d.left=e,d.center=t,d.right=e,this._refreshDrawHeightConstants(),_.full=0,_.left=0,_.center=d.left,_.right=d.left+d.center}_refreshDrawHeightConstants(){l.full=Math.round(2*this._coreBrowseService.dpr);const e=this._canvas.height/this._bufferService.buffer.lines.length,t=Math.round(Math.max(Math.min(e,12),6)*this._coreBrowseService.dpr);l.left=t,l.center=t,l.right=t}_refreshColorZonePadding(){this._colorZoneStore.setPadding({full:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*l.full),left:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*l.left),center:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*l.center),right:Math.floor(this._bufferService.buffers.active.lines.length/(this._canvas.height-1)*l.right)}),this._lastKnownBufferLength=this._bufferService.buffers.normal.lines.length}_refreshCanvasDimensions(){this._canvas.style.width=`${this._width}px`,this._canvas.width=Math.round(this._width*this._coreBrowseService.dpr),this._canvas.style.height=`${this._screenElement.clientHeight}px`,this._canvas.height=Math.round(this._screenElement.clientHeight*this._coreBrowseService.dpr),this._refreshDrawConstants(),this._refreshColorZonePadding()}_refreshDecorations(){this._shouldUpdateDimensions&&this._refreshCanvasDimensions(),this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height),this._colorZoneStore.clear();for(const e of this._decorationService.decorations)this._colorZoneStore.addDecoration(e);this._ctx.lineWidth=1;const e=this._colorZoneStore.zones;for(const t of e)"full"!==t.position&&this._renderColorZone(t);for(const t of e)"full"===t.position&&this._renderColorZone(t);this._shouldUpdateDimensions=!1,this._shouldUpdateAnchor=!1}_renderColorZone(e){this._ctx.fillStyle=e.color,this._ctx.fillRect(_[e.position||"full"],Math.round((this._canvas.height-1)*(e.startBufferLine/this._bufferService.buffers.active.lines.length)-l[e.position||"full"]/2),d[e.position||"full"],Math.round((this._canvas.height-1)*((e.endBufferLine-e.startBufferLine)/this._bufferService.buffers.active.lines.length)+l[e.position||"full"]))}_queueRefresh(e,t){this._shouldUpdateDimensions=e||this._shouldUpdateDimensions,this._shouldUpdateAnchor=t||this._shouldUpdateAnchor,void 0===this._animationFrame&&(this._animationFrame=this._coreBrowseService.window.requestAnimationFrame((()=>{this._refreshDecorations(),this._animationFrame=void 0})))}};t.OverviewRulerRenderer=u=s([r(2,c.IBufferService),r(3,c.IDecorationService),r(4,a.IRenderService),r(5,c.IOptionsService),r(6,a.ICoreBrowserService)],u)},2950:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CompositionHelper=void 0;const n=i(4725),o=i(2585),a=i(2584);let h=t.CompositionHelper=class{get isComposing(){return this._isComposing}constructor(e,t,i,s,r,n){this._textarea=e,this._compositionView=t,this._bufferService=i,this._optionsService=s,this._coreService=r,this._renderService=n,this._isComposing=!1,this._isSendingComposition=!1,this._compositionPosition={start:0,end:0},this._dataAlreadySent=""}compositionstart(){this._isComposing=!0,this._compositionPosition.start=this._textarea.value.length,this._compositionView.textContent="",this._dataAlreadySent="",this._compositionView.classList.add("active")}compositionupdate(e){this._compositionView.textContent=e.data,this.updateCompositionElements(),setTimeout((()=>{this._compositionPosition.end=this._textarea.value.length}),0)}compositionend(){this._finalizeComposition(!0)}keydown(e){if(this._isComposing||this._isSendingComposition){if(229===e.keyCode)return!1;if(16===e.keyCode||17===e.keyCode||18===e.keyCode)return!1;this._finalizeComposition(!1)}return 229!==e.keyCode||(this._handleAnyTextareaChanges(),!1)}_finalizeComposition(e){if(this._compositionView.classList.remove("active"),this._isComposing=!1,e){const e={start:this._compositionPosition.start,end:this._compositionPosition.end};this._isSendingComposition=!0,setTimeout((()=>{if(this._isSendingComposition){let t;this._isSendingComposition=!1,e.start+=this._dataAlreadySent.length,t=this._isComposing?this._textarea.value.substring(e.start,e.end):this._textarea.value.substring(e.start),t.length>0&&this._coreService.triggerDataEvent(t,!0)}}),0)}else{this._isSendingComposition=!1;const e=this._textarea.value.substring(this._compositionPosition.start,this._compositionPosition.end);this._coreService.triggerDataEvent(e,!0)}}_handleAnyTextareaChanges(){const e=this._textarea.value;setTimeout((()=>{if(!this._isComposing){const t=this._textarea.value,i=t.replace(e,"");this._dataAlreadySent=i,t.length>e.length?this._coreService.triggerDataEvent(i,!0):t.lengththis.updateCompositionElements(!0)),0)}}};t.CompositionHelper=h=s([r(2,o.IBufferService),r(3,o.IOptionsService),r(4,o.ICoreService),r(5,n.IRenderService)],h)},9806:(e,t)=>{function i(e,t,i){const s=i.getBoundingClientRect(),r=e.getComputedStyle(i),n=parseInt(r.getPropertyValue("padding-left")),o=parseInt(r.getPropertyValue("padding-top"));return[t.clientX-s.left-n,t.clientY-s.top-o]}Object.defineProperty(t,"__esModule",{value:!0}),t.getCoords=t.getCoordsRelativeToElement=void 0,t.getCoordsRelativeToElement=i,t.getCoords=function(e,t,s,r,n,o,a,h,c){if(!o)return;const l=i(e,t,s);return l?(l[0]=Math.ceil((l[0]+(c?a/2:0))/a),l[1]=Math.ceil(l[1]/h),l[0]=Math.min(Math.max(l[0],1),r+(c?1:0)),l[1]=Math.min(Math.max(l[1],1),n),l):void 0}},9504:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.moveToCellSequence=void 0;const s=i(2584);function r(e,t,i,s){const r=e-n(e,i),a=t-n(t,i),l=Math.abs(r-a)-function(e,t,i){let s=0;const r=e-n(e,i),a=t-n(t,i);for(let n=0;n=0&&et?"A":"B"}function a(e,t,i,s,r,n){let o=e,a=t,h="";for(;o!==i||a!==s;)o+=r?1:-1,r&&o>n.cols-1?(h+=n.buffer.translateBufferLineToString(a,!1,e,o),o=0,e=0,a++):!r&&o<0&&(h+=n.buffer.translateBufferLineToString(a,!1,0,e+1),o=n.cols-1,e=o,a--);return h+n.buffer.translateBufferLineToString(a,!1,e,o)}function h(e,t){const i=t?"O":"[";return s.C0.ESC+i+e}function c(e,t){e=Math.floor(e);let i="";for(let s=0;s0?s-n(s,o):t;const _=s,u=function(e,t,i,s,o,a){let h;return h=r(i,s,o,a).length>0?s-n(s,o):t,e=i&&he?"D":"C",c(Math.abs(o-e),h(d,s));d=l>t?"D":"C";const _=Math.abs(l-t);return c(function(e,t){return t.cols-e}(l>t?e:o,i)+(_-1)*i.cols+1+((l>t?o:e)-1),h(d,s))}},1296:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.DomRenderer=void 0;const n=i(3787),o=i(2550),a=i(2223),h=i(6171),c=i(4725),l=i(8055),d=i(8460),_=i(844),u=i(2585),f="xterm-dom-renderer-owner-",v="xterm-rows",p="xterm-fg-",g="xterm-bg-",m="xterm-focus",S="xterm-selection";let C=1,b=t.DomRenderer=class extends _.Disposable{constructor(e,t,i,s,r,a,c,l,u,p){super(),this._element=e,this._screenElement=t,this._viewportElement=i,this._linkifier2=s,this._charSizeService=a,this._optionsService=c,this._bufferService=l,this._coreBrowserService=u,this._themeService=p,this._terminalClass=C++,this._rowElements=[],this.onRequestRedraw=this.register(new d.EventEmitter).event,this._rowContainer=document.createElement("div"),this._rowContainer.classList.add(v),this._rowContainer.style.lineHeight="normal",this._rowContainer.setAttribute("aria-hidden","true"),this._refreshRowElements(this._bufferService.cols,this._bufferService.rows),this._selectionContainer=document.createElement("div"),this._selectionContainer.classList.add(S),this._selectionContainer.setAttribute("aria-hidden","true"),this.dimensions=(0,h.createRenderDimensions)(),this._updateDimensions(),this.register(this._optionsService.onOptionChange((()=>this._handleOptionsChanged()))),this.register(this._themeService.onChangeColors((e=>this._injectCss(e)))),this._injectCss(this._themeService.colors),this._rowFactory=r.createInstance(n.DomRendererRowFactory,document),this._element.classList.add(f+this._terminalClass),this._screenElement.appendChild(this._rowContainer),this._screenElement.appendChild(this._selectionContainer),this.register(this._linkifier2.onShowLinkUnderline((e=>this._handleLinkHover(e)))),this.register(this._linkifier2.onHideLinkUnderline((e=>this._handleLinkLeave(e)))),this.register((0,_.toDisposable)((()=>{this._element.classList.remove(f+this._terminalClass),this._rowContainer.remove(),this._selectionContainer.remove(),this._widthCache.dispose(),this._themeStyleElement.remove(),this._dimensionsStyleElement.remove()}))),this._widthCache=new o.WidthCache(document),this._widthCache.setFont(this._optionsService.rawOptions.fontFamily,this._optionsService.rawOptions.fontSize,this._optionsService.rawOptions.fontWeight,this._optionsService.rawOptions.fontWeightBold),this._setDefaultSpacing()}_updateDimensions(){const e=this._coreBrowserService.dpr;this.dimensions.device.char.width=this._charSizeService.width*e,this.dimensions.device.char.height=Math.ceil(this._charSizeService.height*e),this.dimensions.device.cell.width=this.dimensions.device.char.width+Math.round(this._optionsService.rawOptions.letterSpacing),this.dimensions.device.cell.height=Math.floor(this.dimensions.device.char.height*this._optionsService.rawOptions.lineHeight),this.dimensions.device.char.left=0,this.dimensions.device.char.top=0,this.dimensions.device.canvas.width=this.dimensions.device.cell.width*this._bufferService.cols,this.dimensions.device.canvas.height=this.dimensions.device.cell.height*this._bufferService.rows,this.dimensions.css.canvas.width=Math.round(this.dimensions.device.canvas.width/e),this.dimensions.css.canvas.height=Math.round(this.dimensions.device.canvas.height/e),this.dimensions.css.cell.width=this.dimensions.css.canvas.width/this._bufferService.cols,this.dimensions.css.cell.height=this.dimensions.css.canvas.height/this._bufferService.rows;for(const e of this._rowElements)e.style.width=`${this.dimensions.css.canvas.width}px`,e.style.height=`${this.dimensions.css.cell.height}px`,e.style.lineHeight=`${this.dimensions.css.cell.height}px`,e.style.overflow="hidden";this._dimensionsStyleElement||(this._dimensionsStyleElement=document.createElement("style"),this._screenElement.appendChild(this._dimensionsStyleElement));const t=`${this._terminalSelector} .${v} span { display: inline-block; height: 100%; vertical-align: top;}`;this._dimensionsStyleElement.textContent=t,this._selectionContainer.style.height=this._viewportElement.style.height,this._screenElement.style.width=`${this.dimensions.css.canvas.width}px`,this._screenElement.style.height=`${this.dimensions.css.canvas.height}px`}_injectCss(e){this._themeStyleElement||(this._themeStyleElement=document.createElement("style"),this._screenElement.appendChild(this._themeStyleElement));let t=`${this._terminalSelector} .${v} { color: ${e.foreground.css}; font-family: ${this._optionsService.rawOptions.fontFamily}; font-size: ${this._optionsService.rawOptions.fontSize}px; font-kerning: none; white-space: pre}`;t+=`${this._terminalSelector} .${v} .xterm-dim { color: ${l.color.multiplyOpacity(e.foreground,.5).css};}`,t+=`${this._terminalSelector} span:not(.xterm-bold) { font-weight: ${this._optionsService.rawOptions.fontWeight};}${this._terminalSelector} span.xterm-bold { font-weight: ${this._optionsService.rawOptions.fontWeightBold};}${this._terminalSelector} span.xterm-italic { font-style: italic;}`,t+="@keyframes blink_box_shadow_"+this._terminalClass+" { 50% { border-bottom-style: hidden; }}",t+="@keyframes blink_block_"+this._terminalClass+" { 0% {"+` background-color: ${e.cursor.css};`+` color: ${e.cursorAccent.css}; } 50% { background-color: inherit;`+` color: ${e.cursor.css}; }}`,t+=`${this._terminalSelector} .${v}.${m} .xterm-cursor.xterm-cursor-blink:not(.xterm-cursor-block) { animation: blink_box_shadow_`+this._terminalClass+" 1s step-end infinite;}"+`${this._terminalSelector} .${v}.${m} .xterm-cursor.xterm-cursor-blink.xterm-cursor-block { animation: blink_block_`+this._terminalClass+" 1s step-end infinite;}"+`${this._terminalSelector} .${v} .xterm-cursor.xterm-cursor-block {`+` background-color: ${e.cursor.css};`+` color: ${e.cursorAccent.css};}`+`${this._terminalSelector} .${v} .xterm-cursor.xterm-cursor-outline {`+` outline: 1px solid ${e.cursor.css}; outline-offset: -1px;}`+`${this._terminalSelector} .${v} .xterm-cursor.xterm-cursor-bar {`+` box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${e.cursor.css} inset;}`+`${this._terminalSelector} .${v} .xterm-cursor.xterm-cursor-underline {`+` border-bottom: 1px ${e.cursor.css}; border-bottom-style: solid; height: calc(100% - 1px);}`,t+=`${this._terminalSelector} .${S} { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none;}${this._terminalSelector}.focus .${S} div { position: absolute; background-color: ${e.selectionBackgroundOpaque.css};}${this._terminalSelector} .${S} div { position: absolute; background-color: ${e.selectionInactiveBackgroundOpaque.css};}`;for(const[i,s]of e.ansi.entries())t+=`${this._terminalSelector} .${p}${i} { color: ${s.css}; }${this._terminalSelector} .${p}${i}.xterm-dim { color: ${l.color.multiplyOpacity(s,.5).css}; }${this._terminalSelector} .${g}${i} { background-color: ${s.css}; }`;t+=`${this._terminalSelector} .${p}${a.INVERTED_DEFAULT_COLOR} { color: ${l.color.opaque(e.background).css}; }${this._terminalSelector} .${p}${a.INVERTED_DEFAULT_COLOR}.xterm-dim { color: ${l.color.multiplyOpacity(l.color.opaque(e.background),.5).css}; }${this._terminalSelector} .${g}${a.INVERTED_DEFAULT_COLOR} { background-color: ${e.foreground.css}; }`,this._themeStyleElement.textContent=t}_setDefaultSpacing(){const e=this.dimensions.css.cell.width-this._widthCache.get("W",!1,!1);this._rowContainer.style.letterSpacing=`${e}px`,this._rowFactory.defaultSpacing=e}handleDevicePixelRatioChange(){this._updateDimensions(),this._widthCache.clear(),this._setDefaultSpacing()}_refreshRowElements(e,t){for(let e=this._rowElements.length;e<=t;e++){const e=document.createElement("div");this._rowContainer.appendChild(e),this._rowElements.push(e)}for(;this._rowElements.length>t;)this._rowContainer.removeChild(this._rowElements.pop())}handleResize(e,t){this._refreshRowElements(e,t),this._updateDimensions()}handleCharSizeChanged(){this._updateDimensions(),this._widthCache.clear(),this._setDefaultSpacing()}handleBlur(){this._rowContainer.classList.remove(m)}handleFocus(){this._rowContainer.classList.add(m),this.renderRows(this._bufferService.buffer.y,this._bufferService.buffer.y)}handleSelectionChanged(e,t,i){if(this._selectionContainer.replaceChildren(),this._rowFactory.handleSelectionChanged(e,t,i),this.renderRows(0,this._bufferService.rows-1),!e||!t)return;const s=e[1]-this._bufferService.buffer.ydisp,r=t[1]-this._bufferService.buffer.ydisp,n=Math.max(s,0),o=Math.min(r,this._bufferService.rows-1);if(n>=this._bufferService.rows||o<0)return;const a=document.createDocumentFragment();if(i){const i=e[0]>t[0];a.appendChild(this._createSelectionElement(n,i?t[0]:e[0],i?e[0]:t[0],o-n+1))}else{const i=s===n?e[0]:0,h=n===r?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(n,i,h));const c=o-n-1;if(a.appendChild(this._createSelectionElement(n+1,0,this._bufferService.cols,c)),n!==o){const e=r===o?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(o,0,e))}}this._selectionContainer.appendChild(a)}_createSelectionElement(e,t,i,s=1){const r=document.createElement("div");return r.style.height=s*this.dimensions.css.cell.height+"px",r.style.top=e*this.dimensions.css.cell.height+"px",r.style.left=t*this.dimensions.css.cell.width+"px",r.style.width=this.dimensions.css.cell.width*(i-t)+"px",r}handleCursorMove(){}_handleOptionsChanged(){this._updateDimensions(),this._injectCss(this._themeService.colors),this._widthCache.setFont(this._optionsService.rawOptions.fontFamily,this._optionsService.rawOptions.fontSize,this._optionsService.rawOptions.fontWeight,this._optionsService.rawOptions.fontWeightBold),this._setDefaultSpacing()}clear(){for(const e of this._rowElements)e.replaceChildren()}renderRows(e,t){const i=this._bufferService.buffer,s=i.ybase+i.y,r=Math.min(i.x,this._bufferService.cols-1),n=this._optionsService.rawOptions.cursorBlink,o=this._optionsService.rawOptions.cursorStyle,a=this._optionsService.rawOptions.cursorInactiveStyle;for(let h=e;h<=t;h++){const e=h+i.ydisp,t=this._rowElements[h],c=i.lines.get(e);if(!t||!c)break;t.replaceChildren(...this._rowFactory.createRow(c,e,e===s,o,a,r,n,this.dimensions.css.cell.width,this._widthCache,-1,-1))}}get _terminalSelector(){return`.${f}${this._terminalClass}`}_handleLinkHover(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!0)}_handleLinkLeave(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!1)}_setCellUnderline(e,t,i,s,r,n){i<0&&(e=0),s<0&&(t=0);const o=this._bufferService.rows-1;i=Math.max(Math.min(i,o),0),s=Math.max(Math.min(s,o),0),r=Math.min(r,this._bufferService.cols);const a=this._bufferService.buffer,h=a.ybase+a.y,c=Math.min(a.x,r-1),l=this._optionsService.rawOptions.cursorBlink,d=this._optionsService.rawOptions.cursorStyle,_=this._optionsService.rawOptions.cursorInactiveStyle;for(let o=i;o<=s;++o){const u=o+a.ydisp,f=this._rowElements[o],v=a.lines.get(u);if(!f||!v)break;f.replaceChildren(...this._rowFactory.createRow(v,u,u===h,d,_,c,l,this.dimensions.css.cell.width,this._widthCache,n?o===i?e:0:-1,n?(o===s?t:r)-1:-1))}}};t.DomRenderer=b=s([r(4,u.IInstantiationService),r(5,c.ICharSizeService),r(6,u.IOptionsService),r(7,u.IBufferService),r(8,c.ICoreBrowserService),r(9,c.IThemeService)],b)},3787:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.DomRendererRowFactory=void 0;const n=i(2223),o=i(643),a=i(511),h=i(2585),c=i(8055),l=i(4725),d=i(4269),_=i(6171),u=i(3734);let f=t.DomRendererRowFactory=class{constructor(e,t,i,s,r,n,o){this._document=e,this._characterJoinerService=t,this._optionsService=i,this._coreBrowserService=s,this._coreService=r,this._decorationService=n,this._themeService=o,this._workCell=new a.CellData,this._columnSelectMode=!1,this.defaultSpacing=0}handleSelectionChanged(e,t,i){this._selectionStart=e,this._selectionEnd=t,this._columnSelectMode=i}createRow(e,t,i,s,r,a,h,l,_,f,p){const g=[],m=this._characterJoinerService.getJoinedCharacters(t),S=this._themeService.colors;let C,b=e.getNoBgTrimmedLength();i&&b0&&M===m[0][0]){O=!0;const t=m.shift();I=new d.JoinedCellData(this._workCell,e.translateToString(!0,t[0],t[1]),t[1]-t[0]),P=t[1]-1,b=I.getWidth()}const H=this._isCellInSelection(M,t),F=i&&M===a,W=T&&M>=f&&M<=p;let U=!1;this._decorationService.forEachDecorationAtCell(M,t,void 0,(e=>{U=!0}));let N=I.getChars()||o.WHITESPACE_CELL_CHAR;if(" "===N&&(I.isUnderline()||I.isOverline())&&(N=" "),A=b*l-_.get(N,I.isBold(),I.isItalic()),C){if(y&&(H&&x||!H&&!x&&I.bg===E)&&(H&&x&&S.selectionForeground||I.fg===k)&&I.extended.ext===L&&W===D&&A===R&&!F&&!O&&!U){w+=N,y++;continue}y&&(C.textContent=w),C=this._document.createElement("span"),y=0,w=""}else C=this._document.createElement("span");if(E=I.bg,k=I.fg,L=I.extended.ext,D=W,R=A,x=H,O&&a>=M&&a<=P&&(a=M),!this._coreService.isCursorHidden&&F)if(B.push("xterm-cursor"),this._coreBrowserService.isFocused)h&&B.push("xterm-cursor-blink"),B.push("bar"===s?"xterm-cursor-bar":"underline"===s?"xterm-cursor-underline":"xterm-cursor-block");else if(r)switch(r){case"outline":B.push("xterm-cursor-outline");break;case"block":B.push("xterm-cursor-block");break;case"bar":B.push("xterm-cursor-bar");break;case"underline":B.push("xterm-cursor-underline")}if(I.isBold()&&B.push("xterm-bold"),I.isItalic()&&B.push("xterm-italic"),I.isDim()&&B.push("xterm-dim"),w=I.isInvisible()?o.WHITESPACE_CELL_CHAR:I.getChars()||o.WHITESPACE_CELL_CHAR,I.isUnderline()&&(B.push(`xterm-underline-${I.extended.underlineStyle}`)," "===w&&(w=" "),!I.isUnderlineColorDefault()))if(I.isUnderlineColorRGB())C.style.textDecorationColor=`rgb(${u.AttributeData.toColorRGB(I.getUnderlineColor()).join(",")})`;else{let e=I.getUnderlineColor();this._optionsService.rawOptions.drawBoldTextInBrightColors&&I.isBold()&&e<8&&(e+=8),C.style.textDecorationColor=S.ansi[e].css}I.isOverline()&&(B.push("xterm-overline")," "===w&&(w=" ")),I.isStrikethrough()&&B.push("xterm-strikethrough"),W&&(C.style.textDecoration="underline");let $=I.getFgColor(),j=I.getFgColorMode(),z=I.getBgColor(),K=I.getBgColorMode();const q=!!I.isInverse();if(q){const e=$;$=z,z=e;const t=j;j=K,K=t}let V,G,X,J=!1;switch(this._decorationService.forEachDecorationAtCell(M,t,void 0,(e=>{"top"!==e.options.layer&&J||(e.backgroundColorRGB&&(K=50331648,z=e.backgroundColorRGB.rgba>>8&16777215,V=e.backgroundColorRGB),e.foregroundColorRGB&&(j=50331648,$=e.foregroundColorRGB.rgba>>8&16777215,G=e.foregroundColorRGB),J="top"===e.options.layer)})),!J&&H&&(V=this._coreBrowserService.isFocused?S.selectionBackgroundOpaque:S.selectionInactiveBackgroundOpaque,z=V.rgba>>8&16777215,K=50331648,J=!0,S.selectionForeground&&(j=50331648,$=S.selectionForeground.rgba>>8&16777215,G=S.selectionForeground)),J&&B.push("xterm-decoration-top"),K){case 16777216:case 33554432:X=S.ansi[z],B.push(`xterm-bg-${z}`);break;case 50331648:X=c.rgba.toColor(z>>16,z>>8&255,255&z),this._addStyle(C,`background-color:#${v((z>>>0).toString(16),"0",6)}`);break;default:q?(X=S.foreground,B.push(`xterm-bg-${n.INVERTED_DEFAULT_COLOR}`)):X=S.background}switch(V||I.isDim()&&(V=c.color.multiplyOpacity(X,.5)),j){case 16777216:case 33554432:I.isBold()&&$<8&&this._optionsService.rawOptions.drawBoldTextInBrightColors&&($+=8),this._applyMinimumContrast(C,X,S.ansi[$],I,V,void 0)||B.push(`xterm-fg-${$}`);break;case 50331648:const e=c.rgba.toColor($>>16&255,$>>8&255,255&$);this._applyMinimumContrast(C,X,e,I,V,G)||this._addStyle(C,`color:#${v($.toString(16),"0",6)}`);break;default:this._applyMinimumContrast(C,X,S.foreground,I,V,void 0)||q&&B.push(`xterm-fg-${n.INVERTED_DEFAULT_COLOR}`)}B.length&&(C.className=B.join(" "),B.length=0),F||O||U?C.textContent=w:y++,A!==this.defaultSpacing&&(C.style.letterSpacing=`${A}px`),g.push(C),M=P}return C&&y&&(C.textContent=w),g}_applyMinimumContrast(e,t,i,s,r,n){if(1===this._optionsService.rawOptions.minimumContrastRatio||(0,_.excludeFromContrastRatioDemands)(s.getCode()))return!1;const o=this._getContrastCache(s);let a;if(r||n||(a=o.getColor(t.rgba,i.rgba)),void 0===a){const e=this._optionsService.rawOptions.minimumContrastRatio/(s.isDim()?2:1);a=c.color.ensureContrastRatio(r||t,n||i,e),o.setColor((r||t).rgba,(n||i).rgba,null!=a?a:null)}return!!a&&(this._addStyle(e,`color:${a.css}`),!0)}_getContrastCache(e){return e.isDim()?this._themeService.colors.halfContrastCache:this._themeService.colors.contrastCache}_addStyle(e,t){e.setAttribute("style",`${e.getAttribute("style")||""}${t};`)}_isCellInSelection(e,t){const i=this._selectionStart,s=this._selectionEnd;return!(!i||!s)&&(this._columnSelectMode?i[0]<=s[0]?e>=i[0]&&t>=i[1]&&e=i[1]&&e>=s[0]&&t<=s[1]:t>i[1]&&t=i[0]&&e=i[0])}};function v(e,t,i){for(;e.length{Object.defineProperty(t,"__esModule",{value:!0}),t.WidthCache=void 0,t.WidthCache=class{constructor(e){this._flat=new Float32Array(256),this._font="",this._fontSize=0,this._weight="normal",this._weightBold="bold",this._measureElements=[],this._container=e.createElement("div"),this._container.style.position="absolute",this._container.style.top="-50000px",this._container.style.width="50000px",this._container.style.whiteSpace="pre",this._container.style.fontKerning="none";const t=e.createElement("span"),i=e.createElement("span");i.style.fontWeight="bold";const s=e.createElement("span");s.style.fontStyle="italic";const r=e.createElement("span");r.style.fontWeight="bold",r.style.fontStyle="italic",this._measureElements=[t,i,s,r],this._container.appendChild(t),this._container.appendChild(i),this._container.appendChild(s),this._container.appendChild(r),e.body.appendChild(this._container),this.clear()}dispose(){this._container.remove(),this._measureElements.length=0,this._holey=void 0}clear(){this._flat.fill(-9999),this._holey=new Map}setFont(e,t,i,s){e===this._font&&t===this._fontSize&&i===this._weight&&s===this._weightBold||(this._font=e,this._fontSize=t,this._weight=i,this._weightBold=s,this._container.style.fontFamily=this._font,this._container.style.fontSize=`${this._fontSize}px`,this._measureElements[0].style.fontWeight=`${i}`,this._measureElements[1].style.fontWeight=`${s}`,this._measureElements[2].style.fontWeight=`${i}`,this._measureElements[3].style.fontWeight=`${s}`,this.clear())}get(e,t,i){let s=0;if(!t&&!i&&1===e.length&&(s=e.charCodeAt(0))<256)return-9999!==this._flat[s]?this._flat[s]:this._flat[s]=this._measure(e,0);let r=e;t&&(r+="B"),i&&(r+="I");let n=this._holey.get(r);if(void 0===n){let s=0;t&&(s|=1),i&&(s|=2),n=this._measure(e,s),this._holey.set(r,n)}return n}_measure(e,t){const i=this._measureElements[t];return i.textContent=e.repeat(32),i.offsetWidth/32}}},2223:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.TEXT_BASELINE=t.DIM_OPACITY=t.INVERTED_DEFAULT_COLOR=void 0;const s=i(6114);t.INVERTED_DEFAULT_COLOR=257,t.DIM_OPACITY=.5,t.TEXT_BASELINE=s.isFirefox||s.isLegacyEdge?"bottom":"ideographic"},6171:(e,t)=>{function i(e){return 57508<=e&&e<=57558}Object.defineProperty(t,"__esModule",{value:!0}),t.createRenderDimensions=t.excludeFromContrastRatioDemands=t.isRestrictedPowerlineGlyph=t.isPowerlineGlyph=t.throwIfFalsy=void 0,t.throwIfFalsy=function(e){if(!e)throw new Error("value must not be falsy");return e},t.isPowerlineGlyph=i,t.isRestrictedPowerlineGlyph=function(e){return 57520<=e&&e<=57527},t.excludeFromContrastRatioDemands=function(e){return i(e)||function(e){return 9472<=e&&e<=9631}(e)},t.createRenderDimensions=function(){return{css:{canvas:{width:0,height:0},cell:{width:0,height:0}},device:{canvas:{width:0,height:0},cell:{width:0,height:0},char:{width:0,height:0,left:0,top:0}}}}},456:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SelectionModel=void 0,t.SelectionModel=class{constructor(e){this._bufferService=e,this.isSelectAllActive=!1,this.selectionStartLength=0}clearSelection(){this.selectionStart=void 0,this.selectionEnd=void 0,this.isSelectAllActive=!1,this.selectionStartLength=0}get finalSelectionStart(){return this.isSelectAllActive?[0,0]:this.selectionEnd&&this.selectionStart&&this.areSelectionValuesReversed()?this.selectionEnd:this.selectionStart}get finalSelectionEnd(){if(this.isSelectAllActive)return[this._bufferService.cols,this._bufferService.buffer.ybase+this._bufferService.rows-1];if(this.selectionStart){if(!this.selectionEnd||this.areSelectionValuesReversed()){const e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?e%this._bufferService.cols==0?[this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)-1]:[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[e,this.selectionStart[1]]}if(this.selectionStartLength&&this.selectionEnd[1]===this.selectionStart[1]){const e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[Math.max(e,this.selectionEnd[0]),this.selectionEnd[1]]}return this.selectionEnd}}areSelectionValuesReversed(){const e=this.selectionStart,t=this.selectionEnd;return!(!e||!t)&&(e[1]>t[1]||e[1]===t[1]&&e[0]>t[0])}handleTrim(e){return this.selectionStart&&(this.selectionStart[1]-=e),this.selectionEnd&&(this.selectionEnd[1]-=e),this.selectionEnd&&this.selectionEnd[1]<0?(this.clearSelection(),!0):(this.selectionStart&&this.selectionStart[1]<0&&(this.selectionStart[1]=0),!1)}}},428:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CharSizeService=void 0;const n=i(2585),o=i(8460),a=i(844);let h=t.CharSizeService=class extends a.Disposable{get hasValidSize(){return this.width>0&&this.height>0}constructor(e,t,i){super(),this._optionsService=i,this.width=0,this.height=0,this._onCharSizeChange=this.register(new o.EventEmitter),this.onCharSizeChange=this._onCharSizeChange.event,this._measureStrategy=new c(e,t,this._optionsService),this.register(this._optionsService.onMultipleOptionChange(["fontFamily","fontSize"],(()=>this.measure())))}measure(){const e=this._measureStrategy.measure();e.width===this.width&&e.height===this.height||(this.width=e.width,this.height=e.height,this._onCharSizeChange.fire())}};t.CharSizeService=h=s([r(2,n.IOptionsService)],h);class c{constructor(e,t,i){this._document=e,this._parentElement=t,this._optionsService=i,this._result={width:0,height:0},this._measureElement=this._document.createElement("span"),this._measureElement.classList.add("xterm-char-measure-element"),this._measureElement.textContent="W".repeat(32),this._measureElement.setAttribute("aria-hidden","true"),this._measureElement.style.whiteSpace="pre",this._measureElement.style.fontKerning="none",this._parentElement.appendChild(this._measureElement)}measure(){this._measureElement.style.fontFamily=this._optionsService.rawOptions.fontFamily,this._measureElement.style.fontSize=`${this._optionsService.rawOptions.fontSize}px`;const e={height:Number(this._measureElement.offsetHeight),width:Number(this._measureElement.offsetWidth)};return 0!==e.width&&0!==e.height&&(this._result.width=e.width/32,this._result.height=Math.ceil(e.height)),this._result}}},4269:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CharacterJoinerService=t.JoinedCellData=void 0;const n=i(3734),o=i(643),a=i(511),h=i(2585);class c extends n.AttributeData{constructor(e,t,i){super(),this.content=0,this.combinedData="",this.fg=e.fg,this.bg=e.bg,this.combinedData=t,this._width=i}isCombined(){return 2097152}getWidth(){return this._width}getChars(){return this.combinedData}getCode(){return 2097151}setFromCharData(e){throw new Error("not implemented")}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.JoinedCellData=c;let l=t.CharacterJoinerService=class e{constructor(e){this._bufferService=e,this._characterJoiners=[],this._nextCharacterJoinerId=0,this._workCell=new a.CellData}register(e){const t={id:this._nextCharacterJoinerId++,handler:e};return this._characterJoiners.push(t),t.id}deregister(e){for(let t=0;t1){const e=this._getJoinedRanges(s,a,n,t,r);for(let t=0;t1){const e=this._getJoinedRanges(s,a,n,t,r);for(let t=0;t{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreBrowserService=void 0,t.CoreBrowserService=class{constructor(e,t){this._textarea=e,this.window=t,this._isFocused=!1,this._cachedIsFocused=void 0,this._textarea.addEventListener("focus",(()=>this._isFocused=!0)),this._textarea.addEventListener("blur",(()=>this._isFocused=!1))}get dpr(){return this.window.devicePixelRatio}get isFocused(){return void 0===this._cachedIsFocused&&(this._cachedIsFocused=this._isFocused&&this._textarea.ownerDocument.hasFocus(),queueMicrotask((()=>this._cachedIsFocused=void 0))),this._cachedIsFocused}}},8934:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.MouseService=void 0;const n=i(4725),o=i(9806);let a=t.MouseService=class{constructor(e,t){this._renderService=e,this._charSizeService=t}getCoords(e,t,i,s,r){return(0,o.getCoords)(window,e,t,i,s,this._charSizeService.hasValidSize,this._renderService.dimensions.css.cell.width,this._renderService.dimensions.css.cell.height,r)}getMouseReportCoords(e,t){const i=(0,o.getCoordsRelativeToElement)(window,e,t);if(this._charSizeService.hasValidSize)return i[0]=Math.min(Math.max(i[0],0),this._renderService.dimensions.css.canvas.width-1),i[1]=Math.min(Math.max(i[1],0),this._renderService.dimensions.css.canvas.height-1),{col:Math.floor(i[0]/this._renderService.dimensions.css.cell.width),row:Math.floor(i[1]/this._renderService.dimensions.css.cell.height),x:Math.floor(i[0]),y:Math.floor(i[1])}}};t.MouseService=a=s([r(0,n.IRenderService),r(1,n.ICharSizeService)],a)},3230:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.RenderService=void 0;const n=i(3656),o=i(6193),a=i(5596),h=i(4725),c=i(8460),l=i(844),d=i(7226),_=i(2585);let u=t.RenderService=class extends l.Disposable{get dimensions(){return this._renderer.value.dimensions}constructor(e,t,i,s,r,h,_,u){if(super(),this._rowCount=e,this._charSizeService=s,this._renderer=this.register(new l.MutableDisposable),this._pausedResizeTask=new d.DebouncedIdleTask,this._isPaused=!1,this._needsFullRefresh=!1,this._isNextRenderRedrawOnly=!0,this._needsSelectionRefresh=!1,this._canvasWidth=0,this._canvasHeight=0,this._selectionState={start:void 0,end:void 0,columnSelectMode:!1},this._onDimensionsChange=this.register(new c.EventEmitter),this.onDimensionsChange=this._onDimensionsChange.event,this._onRenderedViewportChange=this.register(new c.EventEmitter),this.onRenderedViewportChange=this._onRenderedViewportChange.event,this._onRender=this.register(new c.EventEmitter),this.onRender=this._onRender.event,this._onRefreshRequest=this.register(new c.EventEmitter),this.onRefreshRequest=this._onRefreshRequest.event,this._renderDebouncer=new o.RenderDebouncer(_.window,((e,t)=>this._renderRows(e,t))),this.register(this._renderDebouncer),this._screenDprMonitor=new a.ScreenDprMonitor(_.window),this._screenDprMonitor.setListener((()=>this.handleDevicePixelRatioChange())),this.register(this._screenDprMonitor),this.register(h.onResize((()=>this._fullRefresh()))),this.register(h.buffers.onBufferActivate((()=>{var e;return null===(e=this._renderer.value)||void 0===e?void 0:e.clear()}))),this.register(i.onOptionChange((()=>this._handleOptionsChanged()))),this.register(this._charSizeService.onCharSizeChange((()=>this.handleCharSizeChanged()))),this.register(r.onDecorationRegistered((()=>this._fullRefresh()))),this.register(r.onDecorationRemoved((()=>this._fullRefresh()))),this.register(i.onMultipleOptionChange(["customGlyphs","drawBoldTextInBrightColors","letterSpacing","lineHeight","fontFamily","fontSize","fontWeight","fontWeightBold","minimumContrastRatio"],(()=>{this.clear(),this.handleResize(h.cols,h.rows),this._fullRefresh()}))),this.register(i.onMultipleOptionChange(["cursorBlink","cursorStyle"],(()=>this.refreshRows(h.buffer.y,h.buffer.y,!0)))),this.register((0,n.addDisposableDomListener)(_.window,"resize",(()=>this.handleDevicePixelRatioChange()))),this.register(u.onChangeColors((()=>this._fullRefresh()))),"IntersectionObserver"in _.window){const e=new _.window.IntersectionObserver((e=>this._handleIntersectionChange(e[e.length-1])),{threshold:0});e.observe(t),this.register({dispose:()=>e.disconnect()})}}_handleIntersectionChange(e){this._isPaused=void 0===e.isIntersecting?0===e.intersectionRatio:!e.isIntersecting,this._isPaused||this._charSizeService.hasValidSize||this._charSizeService.measure(),!this._isPaused&&this._needsFullRefresh&&(this._pausedResizeTask.flush(),this.refreshRows(0,this._rowCount-1),this._needsFullRefresh=!1)}refreshRows(e,t,i=!1){this._isPaused?this._needsFullRefresh=!0:(i||(this._isNextRenderRedrawOnly=!1),this._renderDebouncer.refresh(e,t,this._rowCount))}_renderRows(e,t){this._renderer.value&&(e=Math.min(e,this._rowCount-1),t=Math.min(t,this._rowCount-1),this._renderer.value.renderRows(e,t),this._needsSelectionRefresh&&(this._renderer.value.handleSelectionChanged(this._selectionState.start,this._selectionState.end,this._selectionState.columnSelectMode),this._needsSelectionRefresh=!1),this._isNextRenderRedrawOnly||this._onRenderedViewportChange.fire({start:e,end:t}),this._onRender.fire({start:e,end:t}),this._isNextRenderRedrawOnly=!0)}resize(e,t){this._rowCount=t,this._fireOnCanvasResize()}_handleOptionsChanged(){this._renderer.value&&(this.refreshRows(0,this._rowCount-1),this._fireOnCanvasResize())}_fireOnCanvasResize(){this._renderer.value&&(this._renderer.value.dimensions.css.canvas.width===this._canvasWidth&&this._renderer.value.dimensions.css.canvas.height===this._canvasHeight||this._onDimensionsChange.fire(this._renderer.value.dimensions))}hasRenderer(){return!!this._renderer.value}setRenderer(e){this._renderer.value=e,this._renderer.value.onRequestRedraw((e=>this.refreshRows(e.start,e.end,!0))),this._needsSelectionRefresh=!0,this._fullRefresh()}addRefreshCallback(e){return this._renderDebouncer.addRefreshCallback(e)}_fullRefresh(){this._isPaused?this._needsFullRefresh=!0:this.refreshRows(0,this._rowCount-1)}clearTextureAtlas(){var e,t;this._renderer.value&&(null===(t=(e=this._renderer.value).clearTextureAtlas)||void 0===t||t.call(e),this._fullRefresh())}handleDevicePixelRatioChange(){this._charSizeService.measure(),this._renderer.value&&(this._renderer.value.handleDevicePixelRatioChange(),this.refreshRows(0,this._rowCount-1))}handleResize(e,t){this._renderer.value&&(this._isPaused?this._pausedResizeTask.set((()=>this._renderer.value.handleResize(e,t))):this._renderer.value.handleResize(e,t),this._fullRefresh())}handleCharSizeChanged(){var e;null===(e=this._renderer.value)||void 0===e||e.handleCharSizeChanged()}handleBlur(){var e;null===(e=this._renderer.value)||void 0===e||e.handleBlur()}handleFocus(){var e;null===(e=this._renderer.value)||void 0===e||e.handleFocus()}handleSelectionChanged(e,t,i){var s;this._selectionState.start=e,this._selectionState.end=t,this._selectionState.columnSelectMode=i,null===(s=this._renderer.value)||void 0===s||s.handleSelectionChanged(e,t,i)}handleCursorMove(){var e;null===(e=this._renderer.value)||void 0===e||e.handleCursorMove()}clear(){var e;null===(e=this._renderer.value)||void 0===e||e.clear()}};t.RenderService=u=s([r(2,_.IOptionsService),r(3,h.ICharSizeService),r(4,_.IDecorationService),r(5,_.IBufferService),r(6,h.ICoreBrowserService),r(7,h.IThemeService)],u)},9312:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.SelectionService=void 0;const n=i(9806),o=i(9504),a=i(456),h=i(4725),c=i(8460),l=i(844),d=i(6114),_=i(4841),u=i(511),f=i(2585),v=String.fromCharCode(160),p=new RegExp(v,"g");let g=t.SelectionService=class extends l.Disposable{constructor(e,t,i,s,r,n,o,h,d){super(),this._element=e,this._screenElement=t,this._linkifier=i,this._bufferService=s,this._coreService=r,this._mouseService=n,this._optionsService=o,this._renderService=h,this._coreBrowserService=d,this._dragScrollAmount=0,this._enabled=!0,this._workCell=new u.CellData,this._mouseDownTimeStamp=0,this._oldHasSelection=!1,this._oldSelectionStart=void 0,this._oldSelectionEnd=void 0,this._onLinuxMouseSelection=this.register(new c.EventEmitter),this.onLinuxMouseSelection=this._onLinuxMouseSelection.event,this._onRedrawRequest=this.register(new c.EventEmitter),this.onRequestRedraw=this._onRedrawRequest.event,this._onSelectionChange=this.register(new c.EventEmitter),this.onSelectionChange=this._onSelectionChange.event,this._onRequestScrollLines=this.register(new c.EventEmitter),this.onRequestScrollLines=this._onRequestScrollLines.event,this._mouseMoveListener=e=>this._handleMouseMove(e),this._mouseUpListener=e=>this._handleMouseUp(e),this._coreService.onUserInput((()=>{this.hasSelection&&this.clearSelection()})),this._trimListener=this._bufferService.buffer.lines.onTrim((e=>this._handleTrim(e))),this.register(this._bufferService.buffers.onBufferActivate((e=>this._handleBufferActivate(e)))),this.enable(),this._model=new a.SelectionModel(this._bufferService),this._activeSelectionMode=0,this.register((0,l.toDisposable)((()=>{this._removeMouseDownListeners()})))}reset(){this.clearSelection()}disable(){this.clearSelection(),this._enabled=!1}enable(){this._enabled=!0}get selectionStart(){return this._model.finalSelectionStart}get selectionEnd(){return this._model.finalSelectionEnd}get hasSelection(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;return!(!e||!t||e[0]===t[0]&&e[1]===t[1])}get selectionText(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;if(!e||!t)return"";const i=this._bufferService.buffer,s=[];if(3===this._activeSelectionMode){if(e[0]===t[0])return"";const r=e[0]e.replace(p," "))).join(d.isWindows?"\r\n":"\n")}clearSelection(){this._model.clearSelection(),this._removeMouseDownListeners(),this.refresh(),this._onSelectionChange.fire()}refresh(e){this._refreshAnimationFrame||(this._refreshAnimationFrame=this._coreBrowserService.window.requestAnimationFrame((()=>this._refresh()))),d.isLinux&&e&&this.selectionText.length&&this._onLinuxMouseSelection.fire(this.selectionText)}_refresh(){this._refreshAnimationFrame=void 0,this._onRedrawRequest.fire({start:this._model.finalSelectionStart,end:this._model.finalSelectionEnd,columnSelectMode:3===this._activeSelectionMode})}_isClickInSelection(e){const t=this._getMouseBufferCoords(e),i=this._model.finalSelectionStart,s=this._model.finalSelectionEnd;return!!(i&&s&&t)&&this._areCoordsInSelection(t,i,s)}isCellInSelection(e,t){const i=this._model.finalSelectionStart,s=this._model.finalSelectionEnd;return!(!i||!s)&&this._areCoordsInSelection([e,t],i,s)}_areCoordsInSelection(e,t,i){return e[1]>t[1]&&e[1]=t[0]&&e[0]=t[0]}_selectWordAtCursor(e,t){var i,s;const r=null===(s=null===(i=this._linkifier.currentLink)||void 0===i?void 0:i.link)||void 0===s?void 0:s.range;if(r)return this._model.selectionStart=[r.start.x-1,r.start.y-1],this._model.selectionStartLength=(0,_.getRangeLength)(r,this._bufferService.cols),this._model.selectionEnd=void 0,!0;const n=this._getMouseBufferCoords(e);return!!n&&(this._selectWordAt(n,t),this._model.selectionEnd=void 0,!0)}selectAll(){this._model.isSelectAllActive=!0,this.refresh(),this._onSelectionChange.fire()}selectLines(e,t){this._model.clearSelection(),e=Math.max(e,0),t=Math.min(t,this._bufferService.buffer.lines.length-1),this._model.selectionStart=[0,e],this._model.selectionEnd=[this._bufferService.cols,t],this.refresh(),this._onSelectionChange.fire()}_handleTrim(e){this._model.handleTrim(e)&&this.refresh()}_getMouseBufferCoords(e){const t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows,!0);if(t)return t[0]--,t[1]--,t[1]+=this._bufferService.buffer.ydisp,t}_getMouseEventScrollAmount(e){let t=(0,n.getCoordsRelativeToElement)(this._coreBrowserService.window,e,this._screenElement)[1];const i=this._renderService.dimensions.css.canvas.height;return t>=0&&t<=i?0:(t>i&&(t-=i),t=Math.min(Math.max(t,-50),50),t/=50,t/Math.abs(t)+Math.round(14*t))}shouldForceSelection(e){return d.isMac?e.altKey&&this._optionsService.rawOptions.macOptionClickForcesSelection:e.shiftKey}handleMouseDown(e){if(this._mouseDownTimeStamp=e.timeStamp,(2!==e.button||!this.hasSelection)&&0===e.button){if(!this._enabled){if(!this.shouldForceSelection(e))return;e.stopPropagation()}e.preventDefault(),this._dragScrollAmount=0,this._enabled&&e.shiftKey?this._handleIncrementalClick(e):1===e.detail?this._handleSingleClick(e):2===e.detail?this._handleDoubleClick(e):3===e.detail&&this._handleTripleClick(e),this._addMouseDownListeners(),this.refresh(!0)}}_addMouseDownListeners(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.addEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.addEventListener("mouseup",this._mouseUpListener)),this._dragScrollIntervalTimer=this._coreBrowserService.window.setInterval((()=>this._dragScroll()),50)}_removeMouseDownListeners(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.removeEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.removeEventListener("mouseup",this._mouseUpListener)),this._coreBrowserService.window.clearInterval(this._dragScrollIntervalTimer),this._dragScrollIntervalTimer=void 0}_handleIncrementalClick(e){this._model.selectionStart&&(this._model.selectionEnd=this._getMouseBufferCoords(e))}_handleSingleClick(e){if(this._model.selectionStartLength=0,this._model.isSelectAllActive=!1,this._activeSelectionMode=this.shouldColumnSelect(e)?3:0,this._model.selectionStart=this._getMouseBufferCoords(e),!this._model.selectionStart)return;this._model.selectionEnd=void 0;const t=this._bufferService.buffer.lines.get(this._model.selectionStart[1]);t&&t.length!==this._model.selectionStart[0]&&0===t.hasWidth(this._model.selectionStart[0])&&this._model.selectionStart[0]++}_handleDoubleClick(e){this._selectWordAtCursor(e,!0)&&(this._activeSelectionMode=1)}_handleTripleClick(e){const t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=2,this._selectLineAt(t[1]))}shouldColumnSelect(e){return e.altKey&&!(d.isMac&&this._optionsService.rawOptions.macOptionClickForcesSelection)}_handleMouseMove(e){if(e.stopImmediatePropagation(),!this._model.selectionStart)return;const t=this._model.selectionEnd?[this._model.selectionEnd[0],this._model.selectionEnd[1]]:null;if(this._model.selectionEnd=this._getMouseBufferCoords(e),!this._model.selectionEnd)return void this.refresh(!0);2===this._activeSelectionMode?this._model.selectionEnd[1]0?this._model.selectionEnd[0]=this._bufferService.cols:this._dragScrollAmount<0&&(this._model.selectionEnd[0]=0));const i=this._bufferService.buffer;if(this._model.selectionEnd[1]0?(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=this._bufferService.cols),this._model.selectionEnd[1]=Math.min(e.ydisp+this._bufferService.rows,e.lines.length-1)):(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=0),this._model.selectionEnd[1]=e.ydisp),this.refresh()}}_handleMouseUp(e){const t=e.timeStamp-this._mouseDownTimeStamp;if(this._removeMouseDownListeners(),this.selectionText.length<=1&&t<500&&e.altKey&&this._optionsService.rawOptions.altClickMovesCursor){if(this._bufferService.buffer.ybase===this._bufferService.buffer.ydisp){const t=this._mouseService.getCoords(e,this._element,this._bufferService.cols,this._bufferService.rows,!1);if(t&&void 0!==t[0]&&void 0!==t[1]){const e=(0,o.moveToCellSequence)(t[0]-1,t[1]-1,this._bufferService,this._coreService.decPrivateModes.applicationCursorKeys);this._coreService.triggerDataEvent(e,!0)}}}else this._fireEventIfSelectionChanged()}_fireEventIfSelectionChanged(){const e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd,i=!(!e||!t||e[0]===t[0]&&e[1]===t[1]);i?e&&t&&(this._oldSelectionStart&&this._oldSelectionEnd&&e[0]===this._oldSelectionStart[0]&&e[1]===this._oldSelectionStart[1]&&t[0]===this._oldSelectionEnd[0]&&t[1]===this._oldSelectionEnd[1]||this._fireOnSelectionChange(e,t,i)):this._oldHasSelection&&this._fireOnSelectionChange(e,t,i)}_fireOnSelectionChange(e,t,i){this._oldSelectionStart=e,this._oldSelectionEnd=t,this._oldHasSelection=i,this._onSelectionChange.fire()}_handleBufferActivate(e){this.clearSelection(),this._trimListener.dispose(),this._trimListener=e.activeBuffer.lines.onTrim((e=>this._handleTrim(e)))}_convertViewportColToCharacterIndex(e,t){let i=t;for(let s=0;t>=s;s++){const r=e.loadCell(s,this._workCell).getChars().length;0===this._workCell.getWidth()?i--:r>1&&t!==s&&(i+=r-1)}return i}setSelection(e,t,i){this._model.clearSelection(),this._removeMouseDownListeners(),this._model.selectionStart=[e,t],this._model.selectionStartLength=i,this.refresh(),this._fireEventIfSelectionChanged()}rightClickSelect(e){this._isClickInSelection(e)||(this._selectWordAtCursor(e,!1)&&this.refresh(!0),this._fireEventIfSelectionChanged())}_getWordAt(e,t,i=!0,s=!0){if(e[0]>=this._bufferService.cols)return;const r=this._bufferService.buffer,n=r.lines.get(e[1]);if(!n)return;const o=r.translateBufferLineToString(e[1],!1);let a=this._convertViewportColToCharacterIndex(n,e[0]),h=a;const c=e[0]-a;let l=0,d=0,_=0,u=0;if(" "===o.charAt(a)){for(;a>0&&" "===o.charAt(a-1);)a--;for(;h1&&(u+=s-1,h+=s-1);t>0&&a>0&&!this._isCharWordSeparator(n.loadCell(t-1,this._workCell));){n.loadCell(t-1,this._workCell);const e=this._workCell.getChars().length;0===this._workCell.getWidth()?(l++,t--):e>1&&(_+=e-1,a-=e-1),a--,t--}for(;i1&&(u+=e-1,h+=e-1),h++,i++}}h++;let f=a+c-l+_,v=Math.min(this._bufferService.cols,h-a+l+d-_-u);if(t||""!==o.slice(a,h).trim()){if(i&&0===f&&32!==n.getCodePoint(0)){const t=r.lines.get(e[1]-1);if(t&&n.isWrapped&&32!==t.getCodePoint(this._bufferService.cols-1)){const t=this._getWordAt([this._bufferService.cols-1,e[1]-1],!1,!0,!1);if(t){const e=this._bufferService.cols-t.start;f-=e,v+=e}}}if(s&&f+v===this._bufferService.cols&&32!==n.getCodePoint(this._bufferService.cols-1)){const t=r.lines.get(e[1]+1);if((null==t?void 0:t.isWrapped)&&32!==t.getCodePoint(0)){const t=this._getWordAt([0,e[1]+1],!1,!1,!0);t&&(v+=t.length)}}return{start:f,length:v}}}_selectWordAt(e,t){const i=this._getWordAt(e,t);if(i){for(;i.start<0;)i.start+=this._bufferService.cols,e[1]--;this._model.selectionStart=[i.start,e[1]],this._model.selectionStartLength=i.length}}_selectToWordAt(e){const t=this._getWordAt(e,!0);if(t){let i=e[1];for(;t.start<0;)t.start+=this._bufferService.cols,i--;if(!this._model.areSelectionValuesReversed())for(;t.start+t.length>this._bufferService.cols;)t.length-=this._bufferService.cols,i++;this._model.selectionEnd=[this._model.areSelectionValuesReversed()?t.start:t.start+t.length,i]}}_isCharWordSeparator(e){return 0!==e.getWidth()&&this._optionsService.rawOptions.wordSeparator.indexOf(e.getChars())>=0}_selectLineAt(e){const t=this._bufferService.buffer.getWrappedRangeForLine(e),i={start:{x:0,y:t.first},end:{x:this._bufferService.cols-1,y:t.last}};this._model.selectionStart=[0,t.first],this._model.selectionEnd=void 0,this._model.selectionStartLength=(0,_.getRangeLength)(i,this._bufferService.cols)}};t.SelectionService=g=s([r(3,f.IBufferService),r(4,f.ICoreService),r(5,h.IMouseService),r(6,f.IOptionsService),r(7,h.IRenderService),r(8,h.ICoreBrowserService)],g)},4725:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.IThemeService=t.ICharacterJoinerService=t.ISelectionService=t.IRenderService=t.IMouseService=t.ICoreBrowserService=t.ICharSizeService=void 0;const s=i(8343);t.ICharSizeService=(0,s.createDecorator)("CharSizeService"),t.ICoreBrowserService=(0,s.createDecorator)("CoreBrowserService"),t.IMouseService=(0,s.createDecorator)("MouseService"),t.IRenderService=(0,s.createDecorator)("RenderService"),t.ISelectionService=(0,s.createDecorator)("SelectionService"),t.ICharacterJoinerService=(0,s.createDecorator)("CharacterJoinerService"),t.IThemeService=(0,s.createDecorator)("ThemeService")},6731:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.ThemeService=t.DEFAULT_ANSI_COLORS=void 0;const n=i(7239),o=i(8055),a=i(8460),h=i(844),c=i(2585),l=o.css.toColor("#ffffff"),d=o.css.toColor("#000000"),_=o.css.toColor("#ffffff"),u=o.css.toColor("#000000"),f={css:"rgba(255, 255, 255, 0.3)",rgba:4294967117};t.DEFAULT_ANSI_COLORS=Object.freeze((()=>{const e=[o.css.toColor("#2e3436"),o.css.toColor("#cc0000"),o.css.toColor("#4e9a06"),o.css.toColor("#c4a000"),o.css.toColor("#3465a4"),o.css.toColor("#75507b"),o.css.toColor("#06989a"),o.css.toColor("#d3d7cf"),o.css.toColor("#555753"),o.css.toColor("#ef2929"),o.css.toColor("#8ae234"),o.css.toColor("#fce94f"),o.css.toColor("#729fcf"),o.css.toColor("#ad7fa8"),o.css.toColor("#34e2e2"),o.css.toColor("#eeeeec")],t=[0,95,135,175,215,255];for(let i=0;i<216;i++){const s=t[i/36%6|0],r=t[i/6%6|0],n=t[i%6];e.push({css:o.channels.toCss(s,r,n),rgba:o.channels.toRgba(s,r,n)})}for(let t=0;t<24;t++){const i=8+10*t;e.push({css:o.channels.toCss(i,i,i),rgba:o.channels.toRgba(i,i,i)})}return e})());let v=t.ThemeService=class extends h.Disposable{get colors(){return this._colors}constructor(e){super(),this._optionsService=e,this._contrastCache=new n.ColorContrastCache,this._halfContrastCache=new n.ColorContrastCache,this._onChangeColors=this.register(new a.EventEmitter),this.onChangeColors=this._onChangeColors.event,this._colors={foreground:l,background:d,cursor:_,cursorAccent:u,selectionForeground:void 0,selectionBackgroundTransparent:f,selectionBackgroundOpaque:o.color.blend(d,f),selectionInactiveBackgroundTransparent:f,selectionInactiveBackgroundOpaque:o.color.blend(d,f),ansi:t.DEFAULT_ANSI_COLORS.slice(),contrastCache:this._contrastCache,halfContrastCache:this._halfContrastCache},this._updateRestoreColors(),this._setTheme(this._optionsService.rawOptions.theme),this.register(this._optionsService.onSpecificOptionChange("minimumContrastRatio",(()=>this._contrastCache.clear()))),this.register(this._optionsService.onSpecificOptionChange("theme",(()=>this._setTheme(this._optionsService.rawOptions.theme))))}_setTheme(e={}){const i=this._colors;if(i.foreground=p(e.foreground,l),i.background=p(e.background,d),i.cursor=p(e.cursor,_),i.cursorAccent=p(e.cursorAccent,u),i.selectionBackgroundTransparent=p(e.selectionBackground,f),i.selectionBackgroundOpaque=o.color.blend(i.background,i.selectionBackgroundTransparent),i.selectionInactiveBackgroundTransparent=p(e.selectionInactiveBackground,i.selectionBackgroundTransparent),i.selectionInactiveBackgroundOpaque=o.color.blend(i.background,i.selectionInactiveBackgroundTransparent),i.selectionForeground=e.selectionForeground?p(e.selectionForeground,o.NULL_COLOR):void 0,i.selectionForeground===o.NULL_COLOR&&(i.selectionForeground=void 0),o.color.isOpaque(i.selectionBackgroundTransparent)){const e=.3;i.selectionBackgroundTransparent=o.color.opacity(i.selectionBackgroundTransparent,e)}if(o.color.isOpaque(i.selectionInactiveBackgroundTransparent)){const e=.3;i.selectionInactiveBackgroundTransparent=o.color.opacity(i.selectionInactiveBackgroundTransparent,e)}if(i.ansi=t.DEFAULT_ANSI_COLORS.slice(),i.ansi[0]=p(e.black,t.DEFAULT_ANSI_COLORS[0]),i.ansi[1]=p(e.red,t.DEFAULT_ANSI_COLORS[1]),i.ansi[2]=p(e.green,t.DEFAULT_ANSI_COLORS[2]),i.ansi[3]=p(e.yellow,t.DEFAULT_ANSI_COLORS[3]),i.ansi[4]=p(e.blue,t.DEFAULT_ANSI_COLORS[4]),i.ansi[5]=p(e.magenta,t.DEFAULT_ANSI_COLORS[5]),i.ansi[6]=p(e.cyan,t.DEFAULT_ANSI_COLORS[6]),i.ansi[7]=p(e.white,t.DEFAULT_ANSI_COLORS[7]),i.ansi[8]=p(e.brightBlack,t.DEFAULT_ANSI_COLORS[8]),i.ansi[9]=p(e.brightRed,t.DEFAULT_ANSI_COLORS[9]),i.ansi[10]=p(e.brightGreen,t.DEFAULT_ANSI_COLORS[10]),i.ansi[11]=p(e.brightYellow,t.DEFAULT_ANSI_COLORS[11]),i.ansi[12]=p(e.brightBlue,t.DEFAULT_ANSI_COLORS[12]),i.ansi[13]=p(e.brightMagenta,t.DEFAULT_ANSI_COLORS[13]),i.ansi[14]=p(e.brightCyan,t.DEFAULT_ANSI_COLORS[14]),i.ansi[15]=p(e.brightWhite,t.DEFAULT_ANSI_COLORS[15]),e.extendedAnsi){const s=Math.min(i.ansi.length-16,e.extendedAnsi.length);for(let r=0;r{Object.defineProperty(t,"__esModule",{value:!0}),t.CircularList=void 0;const s=i(8460),r=i(844);class n extends r.Disposable{constructor(e){super(),this._maxLength=e,this.onDeleteEmitter=this.register(new s.EventEmitter),this.onDelete=this.onDeleteEmitter.event,this.onInsertEmitter=this.register(new s.EventEmitter),this.onInsert=this.onInsertEmitter.event,this.onTrimEmitter=this.register(new s.EventEmitter),this.onTrim=this.onTrimEmitter.event,this._array=new Array(this._maxLength),this._startIndex=0,this._length=0}get maxLength(){return this._maxLength}set maxLength(e){if(this._maxLength===e)return;const t=new Array(e);for(let i=0;ithis._length)for(let t=this._length;t=e;t--)this._array[this._getCyclicIndex(t+i.length)]=this._array[this._getCyclicIndex(t)];for(let t=0;tthis._maxLength){const e=this._length+i.length-this._maxLength;this._startIndex+=e,this._length=this._maxLength,this.onTrimEmitter.fire(e)}else this._length+=i.length}trimStart(e){e>this._length&&(e=this._length),this._startIndex+=e,this._length-=e,this.onTrimEmitter.fire(e)}shiftElements(e,t,i){if(!(t<=0)){if(e<0||e>=this._length)throw new Error("start argument out of range");if(e+i<0)throw new Error("Cannot shift elements in list beyond index 0");if(i>0){for(let s=t-1;s>=0;s--)this.set(e+s+i,this.get(e+s));const s=e+t+i-this._length;if(s>0)for(this._length+=s;this._length>this._maxLength;)this._length--,this._startIndex++,this.onTrimEmitter.fire(1)}else for(let s=0;s{Object.defineProperty(t,"__esModule",{value:!0}),t.clone=void 0,t.clone=function e(t,i=5){if("object"!=typeof t)return t;const s=Array.isArray(t)?[]:{};for(const r in t)s[r]=i<=1?t[r]:t[r]&&e(t[r],i-1);return s}},8055:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.contrastRatio=t.toPaddedHex=t.rgba=t.rgb=t.css=t.color=t.channels=t.NULL_COLOR=void 0;const s=i(6114);let r=0,n=0,o=0,a=0;var h,c,l,d,_;function u(e){const t=e.toString(16);return t.length<2?"0"+t:t}function f(e,t){return e>>0}}(h||(t.channels=h={})),function(e){function t(e,t){return a=Math.round(255*t),[r,n,o]=_.toChannels(e.rgba),{css:h.toCss(r,n,o,a),rgba:h.toRgba(r,n,o,a)}}e.blend=function(e,t){if(a=(255&t.rgba)/255,1===a)return{css:t.css,rgba:t.rgba};const i=t.rgba>>24&255,s=t.rgba>>16&255,c=t.rgba>>8&255,l=e.rgba>>24&255,d=e.rgba>>16&255,_=e.rgba>>8&255;return r=l+Math.round((i-l)*a),n=d+Math.round((s-d)*a),o=_+Math.round((c-_)*a),{css:h.toCss(r,n,o),rgba:h.toRgba(r,n,o)}},e.isOpaque=function(e){return 255==(255&e.rgba)},e.ensureContrastRatio=function(e,t,i){const s=_.ensureContrastRatio(e.rgba,t.rgba,i);if(s)return _.toColor(s>>24&255,s>>16&255,s>>8&255)},e.opaque=function(e){const t=(255|e.rgba)>>>0;return[r,n,o]=_.toChannels(t),{css:h.toCss(r,n,o),rgba:t}},e.opacity=t,e.multiplyOpacity=function(e,i){return a=255&e.rgba,t(e,a*i/255)},e.toColorRGB=function(e){return[e.rgba>>24&255,e.rgba>>16&255,e.rgba>>8&255]}}(c||(t.color=c={})),function(e){let t,i;if(!s.isNode){const e=document.createElement("canvas");e.width=1,e.height=1;const s=e.getContext("2d",{willReadFrequently:!0});s&&(t=s,t.globalCompositeOperation="copy",i=t.createLinearGradient(0,0,1,1))}e.toColor=function(e){if(e.match(/#[\da-f]{3,8}/i))switch(e.length){case 4:return r=parseInt(e.slice(1,2).repeat(2),16),n=parseInt(e.slice(2,3).repeat(2),16),o=parseInt(e.slice(3,4).repeat(2),16),_.toColor(r,n,o);case 5:return r=parseInt(e.slice(1,2).repeat(2),16),n=parseInt(e.slice(2,3).repeat(2),16),o=parseInt(e.slice(3,4).repeat(2),16),a=parseInt(e.slice(4,5).repeat(2),16),_.toColor(r,n,o,a);case 7:return{css:e,rgba:(parseInt(e.slice(1),16)<<8|255)>>>0};case 9:return{css:e,rgba:parseInt(e.slice(1),16)>>>0}}const s=e.match(/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(,\s*(0|1|\d?\.(\d+))\s*)?\)/);if(s)return r=parseInt(s[1]),n=parseInt(s[2]),o=parseInt(s[3]),a=Math.round(255*(void 0===s[5]?1:parseFloat(s[5]))),_.toColor(r,n,o,a);if(!t||!i)throw new Error("css.toColor: Unsupported css format");if(t.fillStyle=i,t.fillStyle=e,"string"!=typeof t.fillStyle)throw new Error("css.toColor: Unsupported css format");if(t.fillRect(0,0,1,1),[r,n,o,a]=t.getImageData(0,0,1,1).data,255!==a)throw new Error("css.toColor: Unsupported css format");return{rgba:h.toRgba(r,n,o,a),css:e}}}(l||(t.css=l={})),function(e){function t(e,t,i){const s=e/255,r=t/255,n=i/255;return.2126*(s<=.03928?s/12.92:Math.pow((s+.055)/1.055,2.4))+.7152*(r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4))+.0722*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))}e.relativeLuminance=function(e){return t(e>>16&255,e>>8&255,255&e)},e.relativeLuminance2=t}(d||(t.rgb=d={})),function(e){function t(e,t,i){const s=e>>24&255,r=e>>16&255,n=e>>8&255;let o=t>>24&255,a=t>>16&255,h=t>>8&255,c=f(d.relativeLuminance2(o,a,h),d.relativeLuminance2(s,r,n));for(;c0||a>0||h>0);)o-=Math.max(0,Math.ceil(.1*o)),a-=Math.max(0,Math.ceil(.1*a)),h-=Math.max(0,Math.ceil(.1*h)),c=f(d.relativeLuminance2(o,a,h),d.relativeLuminance2(s,r,n));return(o<<24|a<<16|h<<8|255)>>>0}function i(e,t,i){const s=e>>24&255,r=e>>16&255,n=e>>8&255;let o=t>>24&255,a=t>>16&255,h=t>>8&255,c=f(d.relativeLuminance2(o,a,h),d.relativeLuminance2(s,r,n));for(;c>>0}e.ensureContrastRatio=function(e,s,r){const n=d.relativeLuminance(e>>8),o=d.relativeLuminance(s>>8);if(f(n,o)>8));if(af(n,d.relativeLuminance(t>>8))?o:t}return o}const a=i(e,s,r),h=f(n,d.relativeLuminance(a>>8));if(hf(n,d.relativeLuminance(i>>8))?a:i}return a}},e.reduceLuminance=t,e.increaseLuminance=i,e.toChannels=function(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]},e.toColor=function(e,t,i,s){return{css:h.toCss(e,t,i,s),rgba:h.toRgba(e,t,i,s)}}}(_||(t.rgba=_={})),t.toPaddedHex=u,t.contrastRatio=f},8969:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreTerminal=void 0;const s=i(844),r=i(2585),n=i(4348),o=i(7866),a=i(744),h=i(7302),c=i(6975),l=i(8460),d=i(1753),_=i(1480),u=i(7994),f=i(9282),v=i(5435),p=i(5981),g=i(2660);let m=!1;class S extends s.Disposable{get onScroll(){return this._onScrollApi||(this._onScrollApi=this.register(new l.EventEmitter),this._onScroll.event((e=>{var t;null===(t=this._onScrollApi)||void 0===t||t.fire(e.position)}))),this._onScrollApi.event}get cols(){return this._bufferService.cols}get rows(){return this._bufferService.rows}get buffers(){return this._bufferService.buffers}get options(){return this.optionsService.options}set options(e){for(const t in e)this.optionsService.options[t]=e[t]}constructor(e){super(),this._windowsWrappingHeuristics=this.register(new s.MutableDisposable),this._onBinary=this.register(new l.EventEmitter),this.onBinary=this._onBinary.event,this._onData=this.register(new l.EventEmitter),this.onData=this._onData.event,this._onLineFeed=this.register(new l.EventEmitter),this.onLineFeed=this._onLineFeed.event,this._onResize=this.register(new l.EventEmitter),this.onResize=this._onResize.event,this._onWriteParsed=this.register(new l.EventEmitter),this.onWriteParsed=this._onWriteParsed.event,this._onScroll=this.register(new l.EventEmitter),this._instantiationService=new n.InstantiationService,this.optionsService=this.register(new h.OptionsService(e)),this._instantiationService.setService(r.IOptionsService,this.optionsService),this._bufferService=this.register(this._instantiationService.createInstance(a.BufferService)),this._instantiationService.setService(r.IBufferService,this._bufferService),this._logService=this.register(this._instantiationService.createInstance(o.LogService)),this._instantiationService.setService(r.ILogService,this._logService),this.coreService=this.register(this._instantiationService.createInstance(c.CoreService)),this._instantiationService.setService(r.ICoreService,this.coreService),this.coreMouseService=this.register(this._instantiationService.createInstance(d.CoreMouseService)),this._instantiationService.setService(r.ICoreMouseService,this.coreMouseService),this.unicodeService=this.register(this._instantiationService.createInstance(_.UnicodeService)),this._instantiationService.setService(r.IUnicodeService,this.unicodeService),this._charsetService=this._instantiationService.createInstance(u.CharsetService),this._instantiationService.setService(r.ICharsetService,this._charsetService),this._oscLinkService=this._instantiationService.createInstance(g.OscLinkService),this._instantiationService.setService(r.IOscLinkService,this._oscLinkService),this._inputHandler=this.register(new v.InputHandler(this._bufferService,this._charsetService,this.coreService,this._logService,this.optionsService,this._oscLinkService,this.coreMouseService,this.unicodeService)),this.register((0,l.forwardEvent)(this._inputHandler.onLineFeed,this._onLineFeed)),this.register(this._inputHandler),this.register((0,l.forwardEvent)(this._bufferService.onResize,this._onResize)),this.register((0,l.forwardEvent)(this.coreService.onData,this._onData)),this.register((0,l.forwardEvent)(this.coreService.onBinary,this._onBinary)),this.register(this.coreService.onRequestScrollToBottom((()=>this.scrollToBottom()))),this.register(this.coreService.onUserInput((()=>this._writeBuffer.handleUserInput()))),this.register(this.optionsService.onMultipleOptionChange(["windowsMode","windowsPty"],(()=>this._handleWindowsPtyOptionChange()))),this.register(this._bufferService.onScroll((e=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp,source:0}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this.register(this._inputHandler.onScroll((e=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp,source:0}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this._writeBuffer=this.register(new p.WriteBuffer(((e,t)=>this._inputHandler.parse(e,t)))),this.register((0,l.forwardEvent)(this._writeBuffer.onWriteParsed,this._onWriteParsed))}write(e,t){this._writeBuffer.write(e,t)}writeSync(e,t){this._logService.logLevel<=r.LogLevelEnum.WARN&&!m&&(this._logService.warn("writeSync is unreliable and will be removed soon."),m=!0),this._writeBuffer.writeSync(e,t)}resize(e,t){isNaN(e)||isNaN(t)||(e=Math.max(e,a.MINIMUM_COLS),t=Math.max(t,a.MINIMUM_ROWS),this._bufferService.resize(e,t))}scroll(e,t=!1){this._bufferService.scroll(e,t)}scrollLines(e,t,i){this._bufferService.scrollLines(e,t,i)}scrollPages(e){this.scrollLines(e*(this.rows-1))}scrollToTop(){this.scrollLines(-this._bufferService.buffer.ydisp)}scrollToBottom(){this.scrollLines(this._bufferService.buffer.ybase-this._bufferService.buffer.ydisp)}scrollToLine(e){const t=e-this._bufferService.buffer.ydisp;0!==t&&this.scrollLines(t)}registerEscHandler(e,t){return this._inputHandler.registerEscHandler(e,t)}registerDcsHandler(e,t){return this._inputHandler.registerDcsHandler(e,t)}registerCsiHandler(e,t){return this._inputHandler.registerCsiHandler(e,t)}registerOscHandler(e,t){return this._inputHandler.registerOscHandler(e,t)}_setup(){this._handleWindowsPtyOptionChange()}reset(){this._inputHandler.reset(),this._bufferService.reset(),this._charsetService.reset(),this.coreService.reset(),this.coreMouseService.reset()}_handleWindowsPtyOptionChange(){let e=!1;const t=this.optionsService.rawOptions.windowsPty;t&&void 0!==t.buildNumber&&void 0!==t.buildNumber?e=!!("conpty"===t.backend&&t.buildNumber<21376):this.optionsService.rawOptions.windowsMode&&(e=!0),e?this._enableWindowsWrappingHeuristics():this._windowsWrappingHeuristics.clear()}_enableWindowsWrappingHeuristics(){if(!this._windowsWrappingHeuristics.value){const e=[];e.push(this.onLineFeed(f.updateWindowsModeWrappedState.bind(null,this._bufferService))),e.push(this.registerCsiHandler({final:"H"},(()=>((0,f.updateWindowsModeWrappedState)(this._bufferService),!1)))),this._windowsWrappingHeuristics.value=(0,s.toDisposable)((()=>{for(const t of e)t.dispose()}))}}}t.CoreTerminal=S},8460:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.forwardEvent=t.EventEmitter=void 0,t.EventEmitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=e=>(this._listeners.push(e),{dispose:()=>{if(!this._disposed)for(let t=0;tt.fire(e)))}},5435:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.InputHandler=t.WindowsOptionsReportType=void 0;const n=i(2584),o=i(7116),a=i(2015),h=i(844),c=i(482),l=i(8437),d=i(8460),_=i(643),u=i(511),f=i(3734),v=i(2585),p=i(6242),g=i(6351),m=i(5941),S={"(":0,")":1,"*":2,"+":3,"-":1,".":2},C=131072;function b(e,t){if(e>24)return t.setWinLines||!1;switch(e){case 1:return!!t.restoreWin;case 2:return!!t.minimizeWin;case 3:return!!t.setWinPosition;case 4:return!!t.setWinSizePixels;case 5:return!!t.raiseWin;case 6:return!!t.lowerWin;case 7:return!!t.refreshWin;case 8:return!!t.setWinSizeChars;case 9:return!!t.maximizeWin;case 10:return!!t.fullscreenWin;case 11:return!!t.getWinState;case 13:return!!t.getWinPosition;case 14:return!!t.getWinSizePixels;case 15:return!!t.getScreenSizePixels;case 16:return!!t.getCellSizePixels;case 18:return!!t.getWinSizeChars;case 19:return!!t.getScreenSizeChars;case 20:return!!t.getIconTitle;case 21:return!!t.getWinTitle;case 22:return!!t.pushTitle;case 23:return!!t.popTitle;case 24:return!!t.setWinLines}return!1}var y;!function(e){e[e.GET_WIN_SIZE_PIXELS=0]="GET_WIN_SIZE_PIXELS",e[e.GET_CELL_SIZE_PIXELS=1]="GET_CELL_SIZE_PIXELS"}(y||(t.WindowsOptionsReportType=y={}));let w=0;class E extends h.Disposable{getAttrData(){return this._curAttrData}constructor(e,t,i,s,r,h,_,f,v=new a.EscapeSequenceParser){super(),this._bufferService=e,this._charsetService=t,this._coreService=i,this._logService=s,this._optionsService=r,this._oscLinkService=h,this._coreMouseService=_,this._unicodeService=f,this._parser=v,this._parseBuffer=new Uint32Array(4096),this._stringDecoder=new c.StringToUtf32,this._utf8Decoder=new c.Utf8ToUtf32,this._workCell=new u.CellData,this._windowTitle="",this._iconName="",this._windowTitleStack=[],this._iconNameStack=[],this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone(),this._onRequestBell=this.register(new d.EventEmitter),this.onRequestBell=this._onRequestBell.event,this._onRequestRefreshRows=this.register(new d.EventEmitter),this.onRequestRefreshRows=this._onRequestRefreshRows.event,this._onRequestReset=this.register(new d.EventEmitter),this.onRequestReset=this._onRequestReset.event,this._onRequestSendFocus=this.register(new d.EventEmitter),this.onRequestSendFocus=this._onRequestSendFocus.event,this._onRequestSyncScrollBar=this.register(new d.EventEmitter),this.onRequestSyncScrollBar=this._onRequestSyncScrollBar.event,this._onRequestWindowsOptionsReport=this.register(new d.EventEmitter),this.onRequestWindowsOptionsReport=this._onRequestWindowsOptionsReport.event,this._onA11yChar=this.register(new d.EventEmitter),this.onA11yChar=this._onA11yChar.event,this._onA11yTab=this.register(new d.EventEmitter),this.onA11yTab=this._onA11yTab.event,this._onCursorMove=this.register(new d.EventEmitter),this.onCursorMove=this._onCursorMove.event,this._onLineFeed=this.register(new d.EventEmitter),this.onLineFeed=this._onLineFeed.event,this._onScroll=this.register(new d.EventEmitter),this.onScroll=this._onScroll.event,this._onTitleChange=this.register(new d.EventEmitter),this.onTitleChange=this._onTitleChange.event,this._onColor=this.register(new d.EventEmitter),this.onColor=this._onColor.event,this._parseStack={paused:!1,cursorStartX:0,cursorStartY:0,decodedLength:0,position:0},this._specialColors=[256,257,258],this.register(this._parser),this._dirtyRowTracker=new k(this._bufferService),this._activeBuffer=this._bufferService.buffer,this.register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._parser.setCsiHandlerFallback(((e,t)=>{this._logService.debug("Unknown CSI code: ",{identifier:this._parser.identToString(e),params:t.toArray()})})),this._parser.setEscHandlerFallback((e=>{this._logService.debug("Unknown ESC code: ",{identifier:this._parser.identToString(e)})})),this._parser.setExecuteHandlerFallback((e=>{this._logService.debug("Unknown EXECUTE code: ",{code:e})})),this._parser.setOscHandlerFallback(((e,t,i)=>{this._logService.debug("Unknown OSC code: ",{identifier:e,action:t,data:i})})),this._parser.setDcsHandlerFallback(((e,t,i)=>{"HOOK"===t&&(i=i.toArray()),this._logService.debug("Unknown DCS code: ",{identifier:this._parser.identToString(e),action:t,payload:i})})),this._parser.setPrintHandler(((e,t,i)=>this.print(e,t,i))),this._parser.registerCsiHandler({final:"@"},(e=>this.insertChars(e))),this._parser.registerCsiHandler({intermediates:" ",final:"@"},(e=>this.scrollLeft(e))),this._parser.registerCsiHandler({final:"A"},(e=>this.cursorUp(e))),this._parser.registerCsiHandler({intermediates:" ",final:"A"},(e=>this.scrollRight(e))),this._parser.registerCsiHandler({final:"B"},(e=>this.cursorDown(e))),this._parser.registerCsiHandler({final:"C"},(e=>this.cursorForward(e))),this._parser.registerCsiHandler({final:"D"},(e=>this.cursorBackward(e))),this._parser.registerCsiHandler({final:"E"},(e=>this.cursorNextLine(e))),this._parser.registerCsiHandler({final:"F"},(e=>this.cursorPrecedingLine(e))),this._parser.registerCsiHandler({final:"G"},(e=>this.cursorCharAbsolute(e))),this._parser.registerCsiHandler({final:"H"},(e=>this.cursorPosition(e))),this._parser.registerCsiHandler({final:"I"},(e=>this.cursorForwardTab(e))),this._parser.registerCsiHandler({final:"J"},(e=>this.eraseInDisplay(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"J"},(e=>this.eraseInDisplay(e,!0))),this._parser.registerCsiHandler({final:"K"},(e=>this.eraseInLine(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"K"},(e=>this.eraseInLine(e,!0))),this._parser.registerCsiHandler({final:"L"},(e=>this.insertLines(e))),this._parser.registerCsiHandler({final:"M"},(e=>this.deleteLines(e))),this._parser.registerCsiHandler({final:"P"},(e=>this.deleteChars(e))),this._parser.registerCsiHandler({final:"S"},(e=>this.scrollUp(e))),this._parser.registerCsiHandler({final:"T"},(e=>this.scrollDown(e))),this._parser.registerCsiHandler({final:"X"},(e=>this.eraseChars(e))),this._parser.registerCsiHandler({final:"Z"},(e=>this.cursorBackwardTab(e))),this._parser.registerCsiHandler({final:"`"},(e=>this.charPosAbsolute(e))),this._parser.registerCsiHandler({final:"a"},(e=>this.hPositionRelative(e))),this._parser.registerCsiHandler({final:"b"},(e=>this.repeatPrecedingCharacter(e))),this._parser.registerCsiHandler({final:"c"},(e=>this.sendDeviceAttributesPrimary(e))),this._parser.registerCsiHandler({prefix:">",final:"c"},(e=>this.sendDeviceAttributesSecondary(e))),this._parser.registerCsiHandler({final:"d"},(e=>this.linePosAbsolute(e))),this._parser.registerCsiHandler({final:"e"},(e=>this.vPositionRelative(e))),this._parser.registerCsiHandler({final:"f"},(e=>this.hVPosition(e))),this._parser.registerCsiHandler({final:"g"},(e=>this.tabClear(e))),this._parser.registerCsiHandler({final:"h"},(e=>this.setMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"h"},(e=>this.setModePrivate(e))),this._parser.registerCsiHandler({final:"l"},(e=>this.resetMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"l"},(e=>this.resetModePrivate(e))),this._parser.registerCsiHandler({final:"m"},(e=>this.charAttributes(e))),this._parser.registerCsiHandler({final:"n"},(e=>this.deviceStatus(e))),this._parser.registerCsiHandler({prefix:"?",final:"n"},(e=>this.deviceStatusPrivate(e))),this._parser.registerCsiHandler({intermediates:"!",final:"p"},(e=>this.softReset(e))),this._parser.registerCsiHandler({intermediates:" ",final:"q"},(e=>this.setCursorStyle(e))),this._parser.registerCsiHandler({final:"r"},(e=>this.setScrollRegion(e))),this._parser.registerCsiHandler({final:"s"},(e=>this.saveCursor(e))),this._parser.registerCsiHandler({final:"t"},(e=>this.windowOptions(e))),this._parser.registerCsiHandler({final:"u"},(e=>this.restoreCursor(e))),this._parser.registerCsiHandler({intermediates:"'",final:"}"},(e=>this.insertColumns(e))),this._parser.registerCsiHandler({intermediates:"'",final:"~"},(e=>this.deleteColumns(e))),this._parser.registerCsiHandler({intermediates:'"',final:"q"},(e=>this.selectProtected(e))),this._parser.registerCsiHandler({intermediates:"$",final:"p"},(e=>this.requestMode(e,!0))),this._parser.registerCsiHandler({prefix:"?",intermediates:"$",final:"p"},(e=>this.requestMode(e,!1))),this._parser.setExecuteHandler(n.C0.BEL,(()=>this.bell())),this._parser.setExecuteHandler(n.C0.LF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.VT,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.FF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.CR,(()=>this.carriageReturn())),this._parser.setExecuteHandler(n.C0.BS,(()=>this.backspace())),this._parser.setExecuteHandler(n.C0.HT,(()=>this.tab())),this._parser.setExecuteHandler(n.C0.SO,(()=>this.shiftOut())),this._parser.setExecuteHandler(n.C0.SI,(()=>this.shiftIn())),this._parser.setExecuteHandler(n.C1.IND,(()=>this.index())),this._parser.setExecuteHandler(n.C1.NEL,(()=>this.nextLine())),this._parser.setExecuteHandler(n.C1.HTS,(()=>this.tabSet())),this._parser.registerOscHandler(0,new p.OscHandler((e=>(this.setTitle(e),this.setIconName(e),!0)))),this._parser.registerOscHandler(1,new p.OscHandler((e=>this.setIconName(e)))),this._parser.registerOscHandler(2,new p.OscHandler((e=>this.setTitle(e)))),this._parser.registerOscHandler(4,new p.OscHandler((e=>this.setOrReportIndexedColor(e)))),this._parser.registerOscHandler(8,new p.OscHandler((e=>this.setHyperlink(e)))),this._parser.registerOscHandler(10,new p.OscHandler((e=>this.setOrReportFgColor(e)))),this._parser.registerOscHandler(11,new p.OscHandler((e=>this.setOrReportBgColor(e)))),this._parser.registerOscHandler(12,new p.OscHandler((e=>this.setOrReportCursorColor(e)))),this._parser.registerOscHandler(104,new p.OscHandler((e=>this.restoreIndexedColor(e)))),this._parser.registerOscHandler(110,new p.OscHandler((e=>this.restoreFgColor(e)))),this._parser.registerOscHandler(111,new p.OscHandler((e=>this.restoreBgColor(e)))),this._parser.registerOscHandler(112,new p.OscHandler((e=>this.restoreCursorColor(e)))),this._parser.registerEscHandler({final:"7"},(()=>this.saveCursor())),this._parser.registerEscHandler({final:"8"},(()=>this.restoreCursor())),this._parser.registerEscHandler({final:"D"},(()=>this.index())),this._parser.registerEscHandler({final:"E"},(()=>this.nextLine())),this._parser.registerEscHandler({final:"H"},(()=>this.tabSet())),this._parser.registerEscHandler({final:"M"},(()=>this.reverseIndex())),this._parser.registerEscHandler({final:"="},(()=>this.keypadApplicationMode())),this._parser.registerEscHandler({final:">"},(()=>this.keypadNumericMode())),this._parser.registerEscHandler({final:"c"},(()=>this.fullReset())),this._parser.registerEscHandler({final:"n"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"o"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"|"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"}"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"~"},(()=>this.setgLevel(1))),this._parser.registerEscHandler({intermediates:"%",final:"@"},(()=>this.selectDefaultCharset())),this._parser.registerEscHandler({intermediates:"%",final:"G"},(()=>this.selectDefaultCharset()));for(const e in o.CHARSETS)this._parser.registerEscHandler({intermediates:"(",final:e},(()=>this.selectCharset("("+e))),this._parser.registerEscHandler({intermediates:")",final:e},(()=>this.selectCharset(")"+e))),this._parser.registerEscHandler({intermediates:"*",final:e},(()=>this.selectCharset("*"+e))),this._parser.registerEscHandler({intermediates:"+",final:e},(()=>this.selectCharset("+"+e))),this._parser.registerEscHandler({intermediates:"-",final:e},(()=>this.selectCharset("-"+e))),this._parser.registerEscHandler({intermediates:".",final:e},(()=>this.selectCharset("."+e))),this._parser.registerEscHandler({intermediates:"/",final:e},(()=>this.selectCharset("/"+e)));this._parser.registerEscHandler({intermediates:"#",final:"8"},(()=>this.screenAlignmentPattern())),this._parser.setErrorHandler((e=>(this._logService.error("Parsing error: ",e),e))),this._parser.registerDcsHandler({intermediates:"$",final:"q"},new g.DcsHandler(((e,t)=>this.requestStatusString(e,t))))}_preserveStack(e,t,i,s){this._parseStack.paused=!0,this._parseStack.cursorStartX=e,this._parseStack.cursorStartY=t,this._parseStack.decodedLength=i,this._parseStack.position=s}_logSlowResolvingAsync(e){this._logService.logLevel<=v.LogLevelEnum.WARN&&Promise.race([e,new Promise(((e,t)=>setTimeout((()=>t("#SLOW_TIMEOUT")),5e3)))]).catch((e=>{if("#SLOW_TIMEOUT"!==e)throw e;console.warn("async parser handler taking longer than 5000 ms")}))}_getCurrentLinkId(){return this._curAttrData.extended.urlId}parse(e,t){let i,s=this._activeBuffer.x,r=this._activeBuffer.y,n=0;const o=this._parseStack.paused;if(o){if(i=this._parser.parse(this._parseBuffer,this._parseStack.decodedLength,t))return this._logSlowResolvingAsync(i),i;s=this._parseStack.cursorStartX,r=this._parseStack.cursorStartY,this._parseStack.paused=!1,e.length>C&&(n=this._parseStack.position+C)}if(this._logService.logLevel<=v.LogLevelEnum.DEBUG&&this._logService.debug("parsing data"+("string"==typeof e?` "${e}"`:` "${Array.prototype.map.call(e,(e=>String.fromCharCode(e))).join("")}"`),"string"==typeof e?e.split("").map((e=>e.charCodeAt(0))):e),this._parseBuffer.lengthC)for(let t=n;t0&&2===u.getWidth(this._activeBuffer.x-1)&&u.setCellFromCodePoint(this._activeBuffer.x-1,0,1,d.fg,d.bg,d.extended);for(let f=t;f=a)if(h){for(;this._activeBuffer.x=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!0),u=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y)}else if(this._activeBuffer.x=a-1,2===r)continue;if(l&&(u.insertCells(this._activeBuffer.x,r,this._activeBuffer.getNullCell(d),d),2===u.getWidth(a-1)&&u.setCellFromCodePoint(a-1,_.NULL_CELL_CODE,_.NULL_CELL_WIDTH,d.fg,d.bg,d.extended)),u.setCellFromCodePoint(this._activeBuffer.x++,s,r,d.fg,d.bg,d.extended),r>0)for(;--r;)u.setCellFromCodePoint(this._activeBuffer.x++,0,0,d.fg,d.bg,d.extended)}else u.getWidth(this._activeBuffer.x-1)?u.addCodepointToCell(this._activeBuffer.x-1,s):u.addCodepointToCell(this._activeBuffer.x-2,s)}i-t>0&&(u.loadCell(this._activeBuffer.x-1,this._workCell),2===this._workCell.getWidth()||this._workCell.getCode()>65535?this._parser.precedingCodepoint=0:this._workCell.isCombined()?this._parser.precedingCodepoint=this._workCell.getChars().charCodeAt(0):this._parser.precedingCodepoint=this._workCell.content),this._activeBuffer.x0&&0===u.getWidth(this._activeBuffer.x)&&!u.hasContent(this._activeBuffer.x)&&u.setCellFromCodePoint(this._activeBuffer.x,0,1,d.fg,d.bg,d.extended),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}registerCsiHandler(e,t){return"t"!==e.final||e.prefix||e.intermediates?this._parser.registerCsiHandler(e,t):this._parser.registerCsiHandler(e,(e=>!b(e.params[0],this._optionsService.rawOptions.windowOptions)||t(e)))}registerDcsHandler(e,t){return this._parser.registerDcsHandler(e,new g.DcsHandler(t))}registerEscHandler(e,t){return this._parser.registerEscHandler(e,t)}registerOscHandler(e,t){return this._parser.registerOscHandler(e,new p.OscHandler(t))}bell(){return this._onRequestBell.fire(),!0}lineFeed(){return this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._optionsService.rawOptions.convertEol&&(this._activeBuffer.x=0),this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData())):this._activeBuffer.y>=this._bufferService.rows?this._activeBuffer.y=this._bufferService.rows-1:this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.x>=this._bufferService.cols&&this._activeBuffer.x--,this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._onLineFeed.fire(),!0}carriageReturn(){return this._activeBuffer.x=0,!0}backspace(){var e;if(!this._coreService.decPrivateModes.reverseWraparound)return this._restrictCursor(),this._activeBuffer.x>0&&this._activeBuffer.x--,!0;if(this._restrictCursor(this._bufferService.cols),this._activeBuffer.x>0)this._activeBuffer.x--;else if(0===this._activeBuffer.x&&this._activeBuffer.y>this._activeBuffer.scrollTop&&this._activeBuffer.y<=this._activeBuffer.scrollBottom&&(null===(e=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y))||void 0===e?void 0:e.isWrapped)){this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.y--,this._activeBuffer.x=this._bufferService.cols-1;const e=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y);e.hasWidth(this._activeBuffer.x)&&!e.hasContent(this._activeBuffer.x)&&this._activeBuffer.x--}return this._restrictCursor(),!0}tab(){if(this._activeBuffer.x>=this._bufferService.cols)return!0;const e=this._activeBuffer.x;return this._activeBuffer.x=this._activeBuffer.nextStop(),this._optionsService.rawOptions.screenReaderMode&&this._onA11yTab.fire(this._activeBuffer.x-e),!0}shiftOut(){return this._charsetService.setgLevel(1),!0}shiftIn(){return this._charsetService.setgLevel(0),!0}_restrictCursor(e=this._bufferService.cols-1){this._activeBuffer.x=Math.min(e,Math.max(0,this._activeBuffer.x)),this._activeBuffer.y=this._coreService.decPrivateModes.origin?Math.min(this._activeBuffer.scrollBottom,Math.max(this._activeBuffer.scrollTop,this._activeBuffer.y)):Math.min(this._bufferService.rows-1,Math.max(0,this._activeBuffer.y)),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_setCursor(e,t){this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._coreService.decPrivateModes.origin?(this._activeBuffer.x=e,this._activeBuffer.y=this._activeBuffer.scrollTop+t):(this._activeBuffer.x=e,this._activeBuffer.y=t),this._restrictCursor(),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_moveCursor(e,t){this._restrictCursor(),this._setCursor(this._activeBuffer.x+e,this._activeBuffer.y+t)}cursorUp(e){const t=this._activeBuffer.y-this._activeBuffer.scrollTop;return t>=0?this._moveCursor(0,-Math.min(t,e.params[0]||1)):this._moveCursor(0,-(e.params[0]||1)),!0}cursorDown(e){const t=this._activeBuffer.scrollBottom-this._activeBuffer.y;return t>=0?this._moveCursor(0,Math.min(t,e.params[0]||1)):this._moveCursor(0,e.params[0]||1),!0}cursorForward(e){return this._moveCursor(e.params[0]||1,0),!0}cursorBackward(e){return this._moveCursor(-(e.params[0]||1),0),!0}cursorNextLine(e){return this.cursorDown(e),this._activeBuffer.x=0,!0}cursorPrecedingLine(e){return this.cursorUp(e),this._activeBuffer.x=0,!0}cursorCharAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}cursorPosition(e){return this._setCursor(e.length>=2?(e.params[1]||1)-1:0,(e.params[0]||1)-1),!0}charPosAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}hPositionRelative(e){return this._moveCursor(e.params[0]||1,0),!0}linePosAbsolute(e){return this._setCursor(this._activeBuffer.x,(e.params[0]||1)-1),!0}vPositionRelative(e){return this._moveCursor(0,e.params[0]||1),!0}hVPosition(e){return this.cursorPosition(e),!0}tabClear(e){const t=e.params[0];return 0===t?delete this._activeBuffer.tabs[this._activeBuffer.x]:3===t&&(this._activeBuffer.tabs={}),!0}cursorForwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.nextStop();return!0}cursorBackwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.prevStop();return!0}selectProtected(e){const t=e.params[0];return 1===t&&(this._curAttrData.bg|=536870912),2!==t&&0!==t||(this._curAttrData.bg&=-536870913),!0}_eraseInBufferLine(e,t,i,s=!1,r=!1){const n=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);n.replaceCells(t,i,this._activeBuffer.getNullCell(this._eraseAttrData()),this._eraseAttrData(),r),s&&(n.isWrapped=!1)}_resetBufferLine(e,t=!1){const i=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);i&&(i.fill(this._activeBuffer.getNullCell(this._eraseAttrData()),t),this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase+e),i.isWrapped=!1)}eraseInDisplay(e,t=!1){let i;switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:for(i=this._activeBuffer.y,this._dirtyRowTracker.markDirty(i),this._eraseInBufferLine(i++,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);i=this._bufferService.cols&&(this._activeBuffer.lines.get(i+1).isWrapped=!1);i--;)this._resetBufferLine(i,t);this._dirtyRowTracker.markDirty(0);break;case 2:for(i=this._bufferService.rows,this._dirtyRowTracker.markDirty(i-1);i--;)this._resetBufferLine(i,t);this._dirtyRowTracker.markDirty(0);break;case 3:const e=this._activeBuffer.lines.length-this._bufferService.rows;e>0&&(this._activeBuffer.lines.trimStart(e),this._activeBuffer.ybase=Math.max(this._activeBuffer.ybase-e,0),this._activeBuffer.ydisp=Math.max(this._activeBuffer.ydisp-e,0),this._onScroll.fire(0))}return!0}eraseInLine(e,t=!1){switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:this._eraseInBufferLine(this._activeBuffer.y,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);break;case 1:this._eraseInBufferLine(this._activeBuffer.y,0,this._activeBuffer.x+1,!1,t);break;case 2:this._eraseInBufferLine(this._activeBuffer.y,0,this._bufferService.cols,!0,t)}return this._dirtyRowTracker.markDirty(this._activeBuffer.y),!0}insertLines(e){this._restrictCursor();let t=e.params[0]||1;if(this._activeBuffer.y>this._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.y0||(this._is("xterm")||this._is("rxvt-unicode")||this._is("screen")?this._coreService.triggerDataEvent(n.C0.ESC+"[?1;2c"):this._is("linux")&&this._coreService.triggerDataEvent(n.C0.ESC+"[?6c")),!0}sendDeviceAttributesSecondary(e){return e.params[0]>0||(this._is("xterm")?this._coreService.triggerDataEvent(n.C0.ESC+"[>0;276;0c"):this._is("rxvt-unicode")?this._coreService.triggerDataEvent(n.C0.ESC+"[>85;95;0c"):this._is("linux")?this._coreService.triggerDataEvent(e.params[0]+"c"):this._is("screen")&&this._coreService.triggerDataEvent(n.C0.ESC+"[>83;40003;0c")),!0}_is(e){return 0===(this._optionsService.rawOptions.termName+"").indexOf(e)}setMode(e){for(let t=0;te?1:2,u=e.params[0];return f=u,v=t?2===u?4:4===u?_(o.modes.insertMode):12===u?3:20===u?_(d.convertEol):0:1===u?_(i.applicationCursorKeys):3===u?d.windowOptions.setWinLines?80===h?2:132===h?1:0:0:6===u?_(i.origin):7===u?_(i.wraparound):8===u?3:9===u?_("X10"===s):12===u?_(d.cursorBlink):25===u?_(!o.isCursorHidden):45===u?_(i.reverseWraparound):66===u?_(i.applicationKeypad):67===u?4:1e3===u?_("VT200"===s):1002===u?_("DRAG"===s):1003===u?_("ANY"===s):1004===u?_(i.sendFocus):1005===u?4:1006===u?_("SGR"===r):1015===u?4:1016===u?_("SGR_PIXELS"===r):1048===u?1:47===u||1047===u||1049===u?_(c===l):2004===u?_(i.bracketedPasteMode):0,o.triggerDataEvent(`${n.C0.ESC}[${t?"":"?"}${f};${v}$y`),!0;var f,v}_updateAttrColor(e,t,i,s,r){return 2===t?(e|=50331648,e&=-16777216,e|=f.AttributeData.fromColorRGB([i,s,r])):5===t&&(e&=-50331904,e|=33554432|255&i),e}_extractColor(e,t,i){const s=[0,0,-1,0,0,0];let r=0,n=0;do{if(s[n+r]=e.params[t+n],e.hasSubParams(t+n)){const i=e.getSubParams(t+n);let o=0;do{5===s[1]&&(r=1),s[n+o+1+r]=i[o]}while(++o=2||2===s[1]&&n+r>=5)break;s[1]&&(r=1)}while(++n+t5)&&(e=1),t.extended.underlineStyle=e,t.fg|=268435456,0===e&&(t.fg&=-268435457),t.updateExtended()}_processSGR0(e){e.fg=l.DEFAULT_ATTR_DATA.fg,e.bg=l.DEFAULT_ATTR_DATA.bg,e.extended=e.extended.clone(),e.extended.underlineStyle=0,e.extended.underlineColor&=-67108864,e.updateExtended()}charAttributes(e){if(1===e.length&&0===e.params[0])return this._processSGR0(this._curAttrData),!0;const t=e.length;let i;const s=this._curAttrData;for(let r=0;r=30&&i<=37?(s.fg&=-50331904,s.fg|=16777216|i-30):i>=40&&i<=47?(s.bg&=-50331904,s.bg|=16777216|i-40):i>=90&&i<=97?(s.fg&=-50331904,s.fg|=16777224|i-90):i>=100&&i<=107?(s.bg&=-50331904,s.bg|=16777224|i-100):0===i?this._processSGR0(s):1===i?s.fg|=134217728:3===i?s.bg|=67108864:4===i?(s.fg|=268435456,this._processUnderline(e.hasSubParams(r)?e.getSubParams(r)[0]:1,s)):5===i?s.fg|=536870912:7===i?s.fg|=67108864:8===i?s.fg|=1073741824:9===i?s.fg|=2147483648:2===i?s.bg|=134217728:21===i?this._processUnderline(2,s):22===i?(s.fg&=-134217729,s.bg&=-134217729):23===i?s.bg&=-67108865:24===i?(s.fg&=-268435457,this._processUnderline(0,s)):25===i?s.fg&=-536870913:27===i?s.fg&=-67108865:28===i?s.fg&=-1073741825:29===i?s.fg&=2147483647:39===i?(s.fg&=-67108864,s.fg|=16777215&l.DEFAULT_ATTR_DATA.fg):49===i?(s.bg&=-67108864,s.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):38===i||48===i||58===i?r+=this._extractColor(e,r,s):53===i?s.bg|=1073741824:55===i?s.bg&=-1073741825:59===i?(s.extended=s.extended.clone(),s.extended.underlineColor=-1,s.updateExtended()):100===i?(s.fg&=-67108864,s.fg|=16777215&l.DEFAULT_ATTR_DATA.fg,s.bg&=-67108864,s.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):this._logService.debug("Unknown SGR attribute: %d.",i);return!0}deviceStatus(e){switch(e.params[0]){case 5:this._coreService.triggerDataEvent(`${n.C0.ESC}[0n`);break;case 6:const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[${e};${t}R`)}return!0}deviceStatusPrivate(e){if(6===e.params[0]){const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[?${e};${t}R`)}return!0}softReset(e){return this._coreService.isCursorHidden=!1,this._onRequestSyncScrollBar.fire(),this._activeBuffer.scrollTop=0,this._activeBuffer.scrollBottom=this._bufferService.rows-1,this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._coreService.reset(),this._charsetService.reset(),this._activeBuffer.savedX=0,this._activeBuffer.savedY=this._activeBuffer.ybase,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,this._coreService.decPrivateModes.origin=!1,!0}setCursorStyle(e){const t=e.params[0]||1;switch(t){case 1:case 2:this._optionsService.options.cursorStyle="block";break;case 3:case 4:this._optionsService.options.cursorStyle="underline";break;case 5:case 6:this._optionsService.options.cursorStyle="bar"}const i=t%2==1;return this._optionsService.options.cursorBlink=i,!0}setScrollRegion(e){const t=e.params[0]||1;let i;return(e.length<2||(i=e.params[1])>this._bufferService.rows||0===i)&&(i=this._bufferService.rows),i>t&&(this._activeBuffer.scrollTop=t-1,this._activeBuffer.scrollBottom=i-1,this._setCursor(0,0)),!0}windowOptions(e){if(!b(e.params[0],this._optionsService.rawOptions.windowOptions))return!0;const t=e.length>1?e.params[1]:0;switch(e.params[0]){case 14:2!==t&&this._onRequestWindowsOptionsReport.fire(y.GET_WIN_SIZE_PIXELS);break;case 16:this._onRequestWindowsOptionsReport.fire(y.GET_CELL_SIZE_PIXELS);break;case 18:this._bufferService&&this._coreService.triggerDataEvent(`${n.C0.ESC}[8;${this._bufferService.rows};${this._bufferService.cols}t`);break;case 22:0!==t&&2!==t||(this._windowTitleStack.push(this._windowTitle),this._windowTitleStack.length>10&&this._windowTitleStack.shift()),0!==t&&1!==t||(this._iconNameStack.push(this._iconName),this._iconNameStack.length>10&&this._iconNameStack.shift());break;case 23:0!==t&&2!==t||this._windowTitleStack.length&&this.setTitle(this._windowTitleStack.pop()),0!==t&&1!==t||this._iconNameStack.length&&this.setIconName(this._iconNameStack.pop())}return!0}saveCursor(e){return this._activeBuffer.savedX=this._activeBuffer.x,this._activeBuffer.savedY=this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,!0}restoreCursor(e){return this._activeBuffer.x=this._activeBuffer.savedX||0,this._activeBuffer.y=Math.max(this._activeBuffer.savedY-this._activeBuffer.ybase,0),this._curAttrData.fg=this._activeBuffer.savedCurAttrData.fg,this._curAttrData.bg=this._activeBuffer.savedCurAttrData.bg,this._charsetService.charset=this._savedCharset,this._activeBuffer.savedCharset&&(this._charsetService.charset=this._activeBuffer.savedCharset),this._restrictCursor(),!0}setTitle(e){return this._windowTitle=e,this._onTitleChange.fire(e),!0}setIconName(e){return this._iconName=e,!0}setOrReportIndexedColor(e){const t=[],i=e.split(";");for(;i.length>1;){const e=i.shift(),s=i.shift();if(/^\d+$/.exec(e)){const i=parseInt(e);if(L(i))if("?"===s)t.push({type:0,index:i});else{const e=(0,m.parseColor)(s);e&&t.push({type:1,index:i,color:e})}}}return t.length&&this._onColor.fire(t),!0}setHyperlink(e){const t=e.split(";");return!(t.length<2)&&(t[1]?this._createHyperlink(t[0],t[1]):!t[0]&&this._finishHyperlink())}_createHyperlink(e,t){this._getCurrentLinkId()&&this._finishHyperlink();const i=e.split(":");let s;const r=i.findIndex((e=>e.startsWith("id=")));return-1!==r&&(s=i[r].slice(3)||void 0),this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=this._oscLinkService.registerLink({id:s,uri:t}),this._curAttrData.updateExtended(),!0}_finishHyperlink(){return this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=0,this._curAttrData.updateExtended(),!0}_setOrReportSpecialColor(e,t){const i=e.split(";");for(let e=0;e=this._specialColors.length);++e,++t)if("?"===i[e])this._onColor.fire([{type:0,index:this._specialColors[t]}]);else{const s=(0,m.parseColor)(i[e]);s&&this._onColor.fire([{type:1,index:this._specialColors[t],color:s}])}return!0}setOrReportFgColor(e){return this._setOrReportSpecialColor(e,0)}setOrReportBgColor(e){return this._setOrReportSpecialColor(e,1)}setOrReportCursorColor(e){return this._setOrReportSpecialColor(e,2)}restoreIndexedColor(e){if(!e)return this._onColor.fire([{type:2}]),!0;const t=[],i=e.split(";");for(let e=0;e=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._restrictCursor(),!0}tabSet(){return this._activeBuffer.tabs[this._activeBuffer.x]=!0,!0}reverseIndex(){if(this._restrictCursor(),this._activeBuffer.y===this._activeBuffer.scrollTop){const e=this._activeBuffer.scrollBottom-this._activeBuffer.scrollTop;this._activeBuffer.lines.shiftElements(this._activeBuffer.ybase+this._activeBuffer.y,e,1),this._activeBuffer.lines.set(this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.getBlankLine(this._eraseAttrData())),this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop,this._activeBuffer.scrollBottom)}else this._activeBuffer.y--,this._restrictCursor();return!0}fullReset(){return this._parser.reset(),this._onRequestReset.fire(),!0}reset(){this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone()}_eraseAttrData(){return this._eraseAttrDataInternal.bg&=-67108864,this._eraseAttrDataInternal.bg|=67108863&this._curAttrData.bg,this._eraseAttrDataInternal}setgLevel(e){return this._charsetService.setgLevel(e),!0}screenAlignmentPattern(){const e=new u.CellData;e.content=1<<22|"E".charCodeAt(0),e.fg=this._curAttrData.fg,e.bg=this._curAttrData.bg,this._setCursor(0,0);for(let t=0;t(this._coreService.triggerDataEvent(`${n.C0.ESC}${e}${n.C0.ESC}\\`),!0))('"q'===e?`P1$r${this._curAttrData.isProtected()?1:0}"q`:'"p'===e?'P1$r61;1"p':"r"===e?`P1$r${i.scrollTop+1};${i.scrollBottom+1}r`:"m"===e?"P1$r0m":" q"===e?`P1$r${{block:2,underline:4,bar:6}[s.cursorStyle]-(s.cursorBlink?1:0)} q`:"P0$r")}markRangeDirty(e,t){this._dirtyRowTracker.markRangeDirty(e,t)}}t.InputHandler=E;let k=class{constructor(e){this._bufferService=e,this.clearRange()}clearRange(){this.start=this._bufferService.buffer.y,this.end=this._bufferService.buffer.y}markDirty(e){ethis.end&&(this.end=e)}markRangeDirty(e,t){e>t&&(w=e,e=t,t=w),ethis.end&&(this.end=t)}markAllDirty(){this.markRangeDirty(0,this._bufferService.rows-1)}};function L(e){return 0<=e&&e<256}k=s([r(0,v.IBufferService)],k)},844:(e,t)=>{function i(e){for(const t of e)t.dispose();e.length=0}Object.defineProperty(t,"__esModule",{value:!0}),t.getDisposeArrayDisposable=t.disposeArray=t.toDisposable=t.MutableDisposable=t.Disposable=void 0,t.Disposable=class{constructor(){this._disposables=[],this._isDisposed=!1}dispose(){this._isDisposed=!0;for(const e of this._disposables)e.dispose();this._disposables.length=0}register(e){return this._disposables.push(e),e}unregister(e){const t=this._disposables.indexOf(e);-1!==t&&this._disposables.splice(t,1)}},t.MutableDisposable=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(e){var t;this._isDisposed||e===this._value||(null===(t=this._value)||void 0===t||t.dispose(),this._value=e)}clear(){this.value=void 0}dispose(){var e;this._isDisposed=!0,null===(e=this._value)||void 0===e||e.dispose(),this._value=void 0}},t.toDisposable=function(e){return{dispose:e}},t.disposeArray=i,t.getDisposeArrayDisposable=function(e){return{dispose:()=>i(e)}}},1505:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.FourKeyMap=t.TwoKeyMap=void 0;class i{constructor(){this._data={}}set(e,t,i){this._data[e]||(this._data[e]={}),this._data[e][t]=i}get(e,t){return this._data[e]?this._data[e][t]:void 0}clear(){this._data={}}}t.TwoKeyMap=i,t.FourKeyMap=class{constructor(){this._data=new i}set(e,t,s,r,n){this._data.get(e,t)||this._data.set(e,t,new i),this._data.get(e,t).set(s,r,n)}get(e,t,i,s){var r;return null===(r=this._data.get(e,t))||void 0===r?void 0:r.get(i,s)}clear(){this._data.clear()}}},6114:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isChromeOS=t.isLinux=t.isWindows=t.isIphone=t.isIpad=t.isMac=t.getSafariVersion=t.isSafari=t.isLegacyEdge=t.isFirefox=t.isNode=void 0,t.isNode="undefined"==typeof navigator;const i=t.isNode?"node":navigator.userAgent,s=t.isNode?"node":navigator.platform;t.isFirefox=i.includes("Firefox"),t.isLegacyEdge=i.includes("Edge"),t.isSafari=/^((?!chrome|android).)*safari/i.test(i),t.getSafariVersion=function(){if(!t.isSafari)return 0;const e=i.match(/Version\/(\d+)/);return null===e||e.length<2?0:parseInt(e[1])},t.isMac=["Macintosh","MacIntel","MacPPC","Mac68K"].includes(s),t.isIpad="iPad"===s,t.isIphone="iPhone"===s,t.isWindows=["Windows","Win16","Win32","WinCE"].includes(s),t.isLinux=s.indexOf("Linux")>=0,t.isChromeOS=/\bCrOS\b/.test(i)},6106:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SortedList=void 0;let i=0;t.SortedList=class{constructor(e){this._getKey=e,this._array=[]}clear(){this._array.length=0}insert(e){0!==this._array.length?(i=this._search(this._getKey(e)),this._array.splice(i,0,e)):this._array.push(e)}delete(e){if(0===this._array.length)return!1;const t=this._getKey(e);if(void 0===t)return!1;if(i=this._search(t),-1===i)return!1;if(this._getKey(this._array[i])!==t)return!1;do{if(this._array[i]===e)return this._array.splice(i,1),!0}while(++i=this._array.length)&&this._getKey(this._array[i])===e))do{yield this._array[i]}while(++i=this._array.length)&&this._getKey(this._array[i])===e))do{t(this._array[i])}while(++i=t;){let s=t+i>>1;const r=this._getKey(this._array[s]);if(r>e)i=s-1;else{if(!(r0&&this._getKey(this._array[s-1])===e;)s--;return s}t=s+1}}return t}}},7226:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DebouncedIdleTask=t.IdleTaskQueue=t.PriorityTaskQueue=void 0;const s=i(6114);class r{constructor(){this._tasks=[],this._i=0}enqueue(e){this._tasks.push(e),this._start()}flush(){for(;this._ir)return s-t<-20&&console.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(s-t))}ms`),void this._start();s=r}this.clear()}}class n extends r{_requestCallback(e){return setTimeout((()=>e(this._createDeadline(16))))}_cancelCallback(e){clearTimeout(e)}_createDeadline(e){const t=Date.now()+e;return{timeRemaining:()=>Math.max(0,t-Date.now())}}}t.PriorityTaskQueue=n,t.IdleTaskQueue=!s.isNode&&"requestIdleCallback"in window?class extends r{_requestCallback(e){return requestIdleCallback(e)}_cancelCallback(e){cancelIdleCallback(e)}}:n,t.DebouncedIdleTask=class{constructor(){this._queue=new t.IdleTaskQueue}set(e){this._queue.clear(),this._queue.enqueue(e)}flush(){this._queue.flush()}}},9282:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.updateWindowsModeWrappedState=void 0;const s=i(643);t.updateWindowsModeWrappedState=function(e){const t=e.buffer.lines.get(e.buffer.ybase+e.buffer.y-1),i=null==t?void 0:t.get(e.cols-1),r=e.buffer.lines.get(e.buffer.ybase+e.buffer.y);r&&i&&(r.isWrapped=i[s.CHAR_DATA_CODE_INDEX]!==s.NULL_CELL_CODE&&i[s.CHAR_DATA_CODE_INDEX]!==s.WHITESPACE_CELL_CODE)}},3734:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ExtendedAttrs=t.AttributeData=void 0;class i{constructor(){this.fg=0,this.bg=0,this.extended=new s}static toColorRGB(e){return[e>>>16&255,e>>>8&255,255&e]}static fromColorRGB(e){return(255&e[0])<<16|(255&e[1])<<8|255&e[2]}clone(){const e=new i;return e.fg=this.fg,e.bg=this.bg,e.extended=this.extended.clone(),e}isInverse(){return 67108864&this.fg}isBold(){return 134217728&this.fg}isUnderline(){return this.hasExtendedAttrs()&&0!==this.extended.underlineStyle?1:268435456&this.fg}isBlink(){return 536870912&this.fg}isInvisible(){return 1073741824&this.fg}isItalic(){return 67108864&this.bg}isDim(){return 134217728&this.bg}isStrikethrough(){return 2147483648&this.fg}isProtected(){return 536870912&this.bg}isOverline(){return 1073741824&this.bg}getFgColorMode(){return 50331648&this.fg}getBgColorMode(){return 50331648&this.bg}isFgRGB(){return 50331648==(50331648&this.fg)}isBgRGB(){return 50331648==(50331648&this.bg)}isFgPalette(){return 16777216==(50331648&this.fg)||33554432==(50331648&this.fg)}isBgPalette(){return 16777216==(50331648&this.bg)||33554432==(50331648&this.bg)}isFgDefault(){return 0==(50331648&this.fg)}isBgDefault(){return 0==(50331648&this.bg)}isAttributeDefault(){return 0===this.fg&&0===this.bg}getFgColor(){switch(50331648&this.fg){case 16777216:case 33554432:return 255&this.fg;case 50331648:return 16777215&this.fg;default:return-1}}getBgColor(){switch(50331648&this.bg){case 16777216:case 33554432:return 255&this.bg;case 50331648:return 16777215&this.bg;default:return-1}}hasExtendedAttrs(){return 268435456&this.bg}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(268435456&this.bg&&~this.extended.underlineColor)switch(50331648&this.extended.underlineColor){case 16777216:case 33554432:return 255&this.extended.underlineColor;case 50331648:return 16777215&this.extended.underlineColor;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return 268435456&this.bg&&~this.extended.underlineColor?50331648&this.extended.underlineColor:this.getFgColorMode()}isUnderlineColorRGB(){return 268435456&this.bg&&~this.extended.underlineColor?50331648==(50331648&this.extended.underlineColor):this.isFgRGB()}isUnderlineColorPalette(){return 268435456&this.bg&&~this.extended.underlineColor?16777216==(50331648&this.extended.underlineColor)||33554432==(50331648&this.extended.underlineColor):this.isFgPalette()}isUnderlineColorDefault(){return 268435456&this.bg&&~this.extended.underlineColor?0==(50331648&this.extended.underlineColor):this.isFgDefault()}getUnderlineStyle(){return 268435456&this.fg?268435456&this.bg?this.extended.underlineStyle:1:0}}t.AttributeData=i;class s{get ext(){return this._urlId?-469762049&this._ext|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(469762048&this._ext)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return 67108863&this._ext}set underlineColor(e){this._ext&=-67108864,this._ext|=67108863&e}get urlId(){return this._urlId}set urlId(e){this._urlId=e}constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}clone(){return new s(this._ext,this._urlId)}isEmpty(){return 0===this.underlineStyle&&0===this._urlId}}t.ExtendedAttrs=s},9092:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Buffer=t.MAX_BUFFER_SIZE=void 0;const s=i(6349),r=i(7226),n=i(3734),o=i(8437),a=i(4634),h=i(511),c=i(643),l=i(4863),d=i(7116);t.MAX_BUFFER_SIZE=4294967295,t.Buffer=class{constructor(e,t,i){this._hasScrollback=e,this._optionsService=t,this._bufferService=i,this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.tabs={},this.savedY=0,this.savedX=0,this.savedCurAttrData=o.DEFAULT_ATTR_DATA.clone(),this.savedCharset=d.DEFAULT_CHARSET,this.markers=[],this._nullCell=h.CellData.fromCharData([0,c.NULL_CELL_CHAR,c.NULL_CELL_WIDTH,c.NULL_CELL_CODE]),this._whitespaceCell=h.CellData.fromCharData([0,c.WHITESPACE_CELL_CHAR,c.WHITESPACE_CELL_WIDTH,c.WHITESPACE_CELL_CODE]),this._isClearing=!1,this._memoryCleanupQueue=new r.IdleTaskQueue,this._memoryCleanupPosition=0,this._cols=this._bufferService.cols,this._rows=this._bufferService.rows,this.lines=new s.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}getNullCell(e){return e?(this._nullCell.fg=e.fg,this._nullCell.bg=e.bg,this._nullCell.extended=e.extended):(this._nullCell.fg=0,this._nullCell.bg=0,this._nullCell.extended=new n.ExtendedAttrs),this._nullCell}getWhitespaceCell(e){return e?(this._whitespaceCell.fg=e.fg,this._whitespaceCell.bg=e.bg,this._whitespaceCell.extended=e.extended):(this._whitespaceCell.fg=0,this._whitespaceCell.bg=0,this._whitespaceCell.extended=new n.ExtendedAttrs),this._whitespaceCell}getBlankLine(e,t){return new o.BufferLine(this._bufferService.cols,this.getNullCell(e),t)}get hasScrollback(){return this._hasScrollback&&this.lines.maxLength>this._rows}get isCursorInViewport(){const e=this.ybase+this.y-this.ydisp;return e>=0&&et.MAX_BUFFER_SIZE?t.MAX_BUFFER_SIZE:i}fillViewportRows(e){if(0===this.lines.length){void 0===e&&(e=o.DEFAULT_ATTR_DATA);let t=this._rows;for(;t--;)this.lines.push(this.getBlankLine(e))}}clear(){this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.lines=new s.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}resize(e,t){const i=this.getNullCell(o.DEFAULT_ATTR_DATA);let s=0;const r=this._getCorrectBufferLength(t);if(r>this.lines.maxLength&&(this.lines.maxLength=r),this.lines.length>0){if(this._cols0&&this.lines.length<=this.ybase+this.y+n+1?(this.ybase--,n++,this.ydisp>0&&this.ydisp--):this.lines.push(new o.BufferLine(e,i)));else for(let e=this._rows;e>t;e--)this.lines.length>t+this.ybase&&(this.lines.length>this.ybase+this.y+1?this.lines.pop():(this.ybase++,this.ydisp++));if(r0&&(this.lines.trimStart(e),this.ybase=Math.max(this.ybase-e,0),this.ydisp=Math.max(this.ydisp-e,0),this.savedY=Math.max(this.savedY-e,0)),this.lines.maxLength=r}this.x=Math.min(this.x,e-1),this.y=Math.min(this.y,t-1),n&&(this.y+=n),this.savedX=Math.min(this.savedX,e-1),this.scrollTop=0}if(this.scrollBottom=t-1,this._isReflowEnabled&&(this._reflow(e,t),this._cols>e))for(let t=0;t.1*this.lines.length&&(this._memoryCleanupPosition=0,this._memoryCleanupQueue.enqueue((()=>this._batchedMemoryCleanup())))}_batchedMemoryCleanup(){let e=!0;this._memoryCleanupPosition>=this.lines.length&&(this._memoryCleanupPosition=0,e=!1);let t=0;for(;this._memoryCleanupPosition100)return!0;return e}get _isReflowEnabled(){const e=this._optionsService.rawOptions.windowsPty;return e&&e.buildNumber?this._hasScrollback&&"conpty"===e.backend&&e.buildNumber>=21376:this._hasScrollback&&!this._optionsService.rawOptions.windowsMode}_reflow(e,t){this._cols!==e&&(e>this._cols?this._reflowLarger(e,t):this._reflowSmaller(e,t))}_reflowLarger(e,t){const i=(0,a.reflowLargerGetLinesToRemove)(this.lines,this._cols,e,this.ybase+this.y,this.getNullCell(o.DEFAULT_ATTR_DATA));if(i.length>0){const s=(0,a.reflowLargerCreateNewLayout)(this.lines,i);(0,a.reflowLargerApplyNewLayout)(this.lines,s.layout),this._reflowLargerAdjustViewport(e,t,s.countRemoved)}}_reflowLargerAdjustViewport(e,t,i){const s=this.getNullCell(o.DEFAULT_ATTR_DATA);let r=i;for(;r-- >0;)0===this.ybase?(this.y>0&&this.y--,this.lines.length=0;n--){let h=this.lines.get(n);if(!h||!h.isWrapped&&h.getTrimmedLength()<=e)continue;const c=[h];for(;h.isWrapped&&n>0;)h=this.lines.get(--n),c.unshift(h);const l=this.ybase+this.y;if(l>=n&&l0&&(s.push({start:n+c.length+r,newLines:v}),r+=v.length),c.push(...v);let p=_.length-1,g=_[p];0===g&&(p--,g=_[p]);let m=c.length-u-1,S=d;for(;m>=0;){const e=Math.min(S,g);if(void 0===c[p])break;if(c[p].copyCellsFrom(c[m],S-e,g-e,e,!0),g-=e,0===g&&(p--,g=_[p]),S-=e,0===S){m--;const e=Math.max(m,0);S=(0,a.getWrappedLineTrimmedLength)(c,e,this._cols)}}for(let t=0;t0;)0===this.ybase?this.y0){const e=[],t=[];for(let e=0;e=0;c--)if(a&&a.start>n+h){for(let e=a.newLines.length-1;e>=0;e--)this.lines.set(c--,a.newLines[e]);c++,e.push({index:n+1,amount:a.newLines.length}),h+=a.newLines.length,a=s[++o]}else this.lines.set(c,t[n--]);let c=0;for(let t=e.length-1;t>=0;t--)e[t].index+=c,this.lines.onInsertEmitter.fire(e[t]),c+=e[t].amount;const l=Math.max(0,i+r-this.lines.maxLength);l>0&&this.lines.onTrimEmitter.fire(l)}}translateBufferLineToString(e,t,i=0,s){const r=this.lines.get(e);return r?r.translateToString(t,i,s):""}getWrappedRangeForLine(e){let t=e,i=e;for(;t>0&&this.lines.get(t).isWrapped;)t--;for(;i+10;);return e>=this._cols?this._cols-1:e<0?0:e}nextStop(e){for(null==e&&(e=this.x);!this.tabs[++e]&&e=this._cols?this._cols-1:e<0?0:e}clearMarkers(e){this._isClearing=!0;for(let t=0;t{t.line-=e,t.line<0&&t.dispose()}))),t.register(this.lines.onInsert((e=>{t.line>=e.index&&(t.line+=e.amount)}))),t.register(this.lines.onDelete((e=>{t.line>=e.index&&t.linee.index&&(t.line-=e.amount)}))),t.register(t.onDispose((()=>this._removeMarker(t)))),t}_removeMarker(e){this._isClearing||this.markers.splice(this.markers.indexOf(e),1)}}},8437:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLine=t.DEFAULT_ATTR_DATA=void 0;const s=i(3734),r=i(511),n=i(643),o=i(482);t.DEFAULT_ATTR_DATA=Object.freeze(new s.AttributeData);let a=0;class h{constructor(e,t,i=!1){this.isWrapped=i,this._combined={},this._extendedAttrs={},this._data=new Uint32Array(3*e);const s=t||r.CellData.fromCharData([0,n.NULL_CELL_CHAR,n.NULL_CELL_WIDTH,n.NULL_CELL_CODE]);for(let t=0;t>22,2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):i]}set(e,t){this._data[3*e+1]=t[n.CHAR_DATA_ATTR_INDEX],t[n.CHAR_DATA_CHAR_INDEX].length>1?(this._combined[e]=t[1],this._data[3*e+0]=2097152|e|t[n.CHAR_DATA_WIDTH_INDEX]<<22):this._data[3*e+0]=t[n.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|t[n.CHAR_DATA_WIDTH_INDEX]<<22}getWidth(e){return this._data[3*e+0]>>22}hasWidth(e){return 12582912&this._data[3*e+0]}getFg(e){return this._data[3*e+1]}getBg(e){return this._data[3*e+2]}hasContent(e){return 4194303&this._data[3*e+0]}getCodePoint(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):2097151&t}isCombined(e){return 2097152&this._data[3*e+0]}getString(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e]:2097151&t?(0,o.stringFromCodePoint)(2097151&t):""}isProtected(e){return 536870912&this._data[3*e+2]}loadCell(e,t){return a=3*e,t.content=this._data[a+0],t.fg=this._data[a+1],t.bg=this._data[a+2],2097152&t.content&&(t.combinedData=this._combined[e]),268435456&t.bg&&(t.extended=this._extendedAttrs[e]),t}setCell(e,t){2097152&t.content&&(this._combined[e]=t.combinedData),268435456&t.bg&&(this._extendedAttrs[e]=t.extended),this._data[3*e+0]=t.content,this._data[3*e+1]=t.fg,this._data[3*e+2]=t.bg}setCellFromCodePoint(e,t,i,s,r,n){268435456&r&&(this._extendedAttrs[e]=n),this._data[3*e+0]=t|i<<22,this._data[3*e+1]=s,this._data[3*e+2]=r}addCodepointToCell(e,t){let i=this._data[3*e+0];2097152&i?this._combined[e]+=(0,o.stringFromCodePoint)(t):(2097151&i?(this._combined[e]=(0,o.stringFromCodePoint)(2097151&i)+(0,o.stringFromCodePoint)(t),i&=-2097152,i|=2097152):i=t|1<<22,this._data[3*e+0]=i)}insertCells(e,t,i,n){if((e%=this.length)&&2===this.getWidth(e-1)&&this.setCellFromCodePoint(e-1,0,1,(null==n?void 0:n.fg)||0,(null==n?void 0:n.bg)||0,(null==n?void 0:n.extended)||new s.ExtendedAttrs),t=0;--i)this.setCell(e+t+i,this.loadCell(e+i,s));for(let s=0;sthis.length){if(this._data.buffer.byteLength>=4*i)this._data=new Uint32Array(this._data.buffer,0,i);else{const e=new Uint32Array(i);e.set(this._data),this._data=e}for(let i=this.length;i=e&&delete this._combined[s]}const s=Object.keys(this._extendedAttrs);for(let t=0;t=e&&delete this._extendedAttrs[i]}}return this.length=e,4*i*2=0;--e)if(4194303&this._data[3*e+0])return e+(this._data[3*e+0]>>22);return 0}getNoBgTrimmedLength(){for(let e=this.length-1;e>=0;--e)if(4194303&this._data[3*e+0]||50331648&this._data[3*e+2])return e+(this._data[3*e+0]>>22);return 0}copyCellsFrom(e,t,i,s,r){const n=e._data;if(r)for(let r=s-1;r>=0;r--){for(let e=0;e<3;e++)this._data[3*(i+r)+e]=n[3*(t+r)+e];268435456&n[3*(t+r)+2]&&(this._extendedAttrs[i+r]=e._extendedAttrs[t+r])}else for(let r=0;r=t&&(this._combined[r-t+i]=e._combined[r])}}translateToString(e=!1,t=0,i=this.length){e&&(i=Math.min(i,this.getTrimmedLength()));let s="";for(;t>22||1}return s}}t.BufferLine=h},4841:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getRangeLength=void 0,t.getRangeLength=function(e,t){if(e.start.y>e.end.y)throw new Error(`Buffer range end (${e.end.x}, ${e.end.y}) cannot be before start (${e.start.x}, ${e.start.y})`);return t*(e.end.y-e.start.y)+(e.end.x-e.start.x+1)}},4634:(e,t)=>{function i(e,t,i){if(t===e.length-1)return e[t].getTrimmedLength();const s=!e[t].hasContent(i-1)&&1===e[t].getWidth(i-1),r=2===e[t+1].getWidth(0);return s&&r?i-1:i}Object.defineProperty(t,"__esModule",{value:!0}),t.getWrappedLineTrimmedLength=t.reflowSmallerGetNewLineLengths=t.reflowLargerApplyNewLayout=t.reflowLargerCreateNewLayout=t.reflowLargerGetLinesToRemove=void 0,t.reflowLargerGetLinesToRemove=function(e,t,s,r,n){const o=[];for(let a=0;a=a&&r0&&(e>d||0===l[e].getTrimmedLength());e--)v++;v>0&&(o.push(a+l.length-v),o.push(v)),a+=l.length-1}return o},t.reflowLargerCreateNewLayout=function(e,t){const i=[];let s=0,r=t[s],n=0;for(let o=0;oi(e,r,t))).reduce(((e,t)=>e+t));let o=0,a=0,h=0;for(;hc&&(o-=c,a++);const l=2===e[a].getWidth(o-1);l&&o--;const d=l?s-1:s;r.push(d),h+=d}return r},t.getWrappedLineTrimmedLength=i},5295:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferSet=void 0;const s=i(8460),r=i(844),n=i(9092);class o extends r.Disposable{constructor(e,t){super(),this._optionsService=e,this._bufferService=t,this._onBufferActivate=this.register(new s.EventEmitter),this.onBufferActivate=this._onBufferActivate.event,this.reset(),this.register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.resize(this._bufferService.cols,this._bufferService.rows)))),this.register(this._optionsService.onSpecificOptionChange("tabStopWidth",(()=>this.setupTabStops())))}reset(){this._normal=new n.Buffer(!0,this._optionsService,this._bufferService),this._normal.fillViewportRows(),this._alt=new n.Buffer(!1,this._optionsService,this._bufferService),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}),this.setupTabStops()}get alt(){return this._alt}get active(){return this._activeBuffer}get normal(){return this._normal}activateNormalBuffer(){this._activeBuffer!==this._normal&&(this._normal.x=this._alt.x,this._normal.y=this._alt.y,this._alt.clearAllMarkers(),this._alt.clear(),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}))}activateAltBuffer(e){this._activeBuffer!==this._alt&&(this._alt.fillViewportRows(e),this._alt.x=this._normal.x,this._alt.y=this._normal.y,this._activeBuffer=this._alt,this._onBufferActivate.fire({activeBuffer:this._alt,inactiveBuffer:this._normal}))}resize(e,t){this._normal.resize(e,t),this._alt.resize(e,t),this.setupTabStops(e)}setupTabStops(e){this._normal.setupTabStops(e),this._alt.setupTabStops(e)}}t.BufferSet=o},511:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CellData=void 0;const s=i(482),r=i(643),n=i(3734);class o extends n.AttributeData{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new n.ExtendedAttrs,this.combinedData=""}static fromCharData(e){const t=new o;return t.setFromCharData(e),t}isCombined(){return 2097152&this.content}getWidth(){return this.content>>22}getChars(){return 2097152&this.content?this.combinedData:2097151&this.content?(0,s.stringFromCodePoint)(2097151&this.content):""}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):2097151&this.content}setFromCharData(e){this.fg=e[r.CHAR_DATA_ATTR_INDEX],this.bg=0;let t=!1;if(e[r.CHAR_DATA_CHAR_INDEX].length>2)t=!0;else if(2===e[r.CHAR_DATA_CHAR_INDEX].length){const i=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0);if(55296<=i&&i<=56319){const s=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(1);56320<=s&&s<=57343?this.content=1024*(i-55296)+s-56320+65536|e[r.CHAR_DATA_WIDTH_INDEX]<<22:t=!0}else t=!0}else this.content=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|e[r.CHAR_DATA_WIDTH_INDEX]<<22;t&&(this.combinedData=e[r.CHAR_DATA_CHAR_INDEX],this.content=2097152|e[r.CHAR_DATA_WIDTH_INDEX]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.CellData=o},643:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WHITESPACE_CELL_CODE=t.WHITESPACE_CELL_WIDTH=t.WHITESPACE_CELL_CHAR=t.NULL_CELL_CODE=t.NULL_CELL_WIDTH=t.NULL_CELL_CHAR=t.CHAR_DATA_CODE_INDEX=t.CHAR_DATA_WIDTH_INDEX=t.CHAR_DATA_CHAR_INDEX=t.CHAR_DATA_ATTR_INDEX=t.DEFAULT_EXT=t.DEFAULT_ATTR=t.DEFAULT_COLOR=void 0,t.DEFAULT_COLOR=0,t.DEFAULT_ATTR=256|t.DEFAULT_COLOR<<9,t.DEFAULT_EXT=0,t.CHAR_DATA_ATTR_INDEX=0,t.CHAR_DATA_CHAR_INDEX=1,t.CHAR_DATA_WIDTH_INDEX=2,t.CHAR_DATA_CODE_INDEX=3,t.NULL_CELL_CHAR="",t.NULL_CELL_WIDTH=1,t.NULL_CELL_CODE=0,t.WHITESPACE_CELL_CHAR=" ",t.WHITESPACE_CELL_WIDTH=1,t.WHITESPACE_CELL_CODE=32},4863:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Marker=void 0;const s=i(8460),r=i(844);class n{get id(){return this._id}constructor(e){this.line=e,this.isDisposed=!1,this._disposables=[],this._id=n._nextId++,this._onDispose=this.register(new s.EventEmitter),this.onDispose=this._onDispose.event}dispose(){this.isDisposed||(this.isDisposed=!0,this.line=-1,this._onDispose.fire(),(0,r.disposeArray)(this._disposables),this._disposables.length=0)}register(e){return this._disposables.push(e),e}}t.Marker=n,n._nextId=1},7116:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_CHARSET=t.CHARSETS=void 0,t.CHARSETS={},t.DEFAULT_CHARSET=t.CHARSETS.B,t.CHARSETS[0]={"`":"◆",a:"▒",b:"␉",c:"␌",d:"␍",e:"␊",f:"°",g:"±",h:"␤",i:"␋",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},t.CHARSETS.A={"#":"£"},t.CHARSETS.B=void 0,t.CHARSETS[4]={"#":"£","@":"¾","[":"ij","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"},t.CHARSETS.C=t.CHARSETS[5]={"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS.R={"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"},t.CHARSETS.Q={"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"},t.CHARSETS.K={"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"},t.CHARSETS.Y={"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"},t.CHARSETS.E=t.CHARSETS[6]={"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"},t.CHARSETS.Z={"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"},t.CHARSETS.H=t.CHARSETS[7]={"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS["="]={"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}},2584:(e,t)=>{var i,s,r;Object.defineProperty(t,"__esModule",{value:!0}),t.C1_ESCAPED=t.C1=t.C0=void 0,function(e){e.NUL="\0",e.SOH="",e.STX="",e.ETX="",e.EOT="",e.ENQ="",e.ACK="",e.BEL="",e.BS="\b",e.HT="\t",e.LF="\n",e.VT="\v",e.FF="\f",e.CR="\r",e.SO="",e.SI="",e.DLE="",e.DC1="",e.DC2="",e.DC3="",e.DC4="",e.NAK="",e.SYN="",e.ETB="",e.CAN="",e.EM="",e.SUB="",e.ESC="",e.FS="",e.GS="",e.RS="",e.US="",e.SP=" ",e.DEL=""}(i||(t.C0=i={})),function(e){e.PAD="€",e.HOP="",e.BPH="‚",e.NBH="ƒ",e.IND="„",e.NEL="…",e.SSA="†",e.ESA="‡",e.HTS="ˆ",e.HTJ="‰",e.VTS="Š",e.PLD="‹",e.PLU="Œ",e.RI="",e.SS2="Ž",e.SS3="",e.DCS="",e.PU1="‘",e.PU2="’",e.STS="“",e.CCH="”",e.MW="•",e.SPA="–",e.EPA="—",e.SOS="˜",e.SGCI="™",e.SCI="š",e.CSI="›",e.ST="œ",e.OSC="",e.PM="ž",e.APC="Ÿ"}(s||(t.C1=s={})),function(e){e.ST=`${i.ESC}\\`}(r||(t.C1_ESCAPED=r={}))},7399:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.evaluateKeyboardEvent=void 0;const s=i(2584),r={48:["0",")"],49:["1","!"],50:["2","@"],51:["3","#"],52:["4","$"],53:["5","%"],54:["6","^"],55:["7","&"],56:["8","*"],57:["9","("],186:[";",":"],187:["=","+"],188:[",","<"],189:["-","_"],190:[".",">"],191:["/","?"],192:["`","~"],219:["[","{"],220:["\\","|"],221:["]","}"],222:["'",'"']};t.evaluateKeyboardEvent=function(e,t,i,n){const o={type:0,cancel:!1,key:void 0},a=(e.shiftKey?1:0)|(e.altKey?2:0)|(e.ctrlKey?4:0)|(e.metaKey?8:0);switch(e.keyCode){case 0:"UIKeyInputUpArrow"===e.key?o.key=t?s.C0.ESC+"OA":s.C0.ESC+"[A":"UIKeyInputLeftArrow"===e.key?o.key=t?s.C0.ESC+"OD":s.C0.ESC+"[D":"UIKeyInputRightArrow"===e.key?o.key=t?s.C0.ESC+"OC":s.C0.ESC+"[C":"UIKeyInputDownArrow"===e.key&&(o.key=t?s.C0.ESC+"OB":s.C0.ESC+"[B");break;case 8:if(e.altKey){o.key=s.C0.ESC+s.C0.DEL;break}o.key=s.C0.DEL;break;case 9:if(e.shiftKey){o.key=s.C0.ESC+"[Z";break}o.key=s.C0.HT,o.cancel=!0;break;case 13:o.key=e.altKey?s.C0.ESC+s.C0.CR:s.C0.CR,o.cancel=!0;break;case 27:o.key=s.C0.ESC,e.altKey&&(o.key=s.C0.ESC+s.C0.ESC),o.cancel=!0;break;case 37:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"D",o.key===s.C0.ESC+"[1;3D"&&(o.key=s.C0.ESC+(i?"b":"[1;5D"))):o.key=t?s.C0.ESC+"OD":s.C0.ESC+"[D";break;case 39:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"C",o.key===s.C0.ESC+"[1;3C"&&(o.key=s.C0.ESC+(i?"f":"[1;5C"))):o.key=t?s.C0.ESC+"OC":s.C0.ESC+"[C";break;case 38:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"A",i||o.key!==s.C0.ESC+"[1;3A"||(o.key=s.C0.ESC+"[1;5A")):o.key=t?s.C0.ESC+"OA":s.C0.ESC+"[A";break;case 40:if(e.metaKey)break;a?(o.key=s.C0.ESC+"[1;"+(a+1)+"B",i||o.key!==s.C0.ESC+"[1;3B"||(o.key=s.C0.ESC+"[1;5B")):o.key=t?s.C0.ESC+"OB":s.C0.ESC+"[B";break;case 45:e.shiftKey||e.ctrlKey||(o.key=s.C0.ESC+"[2~");break;case 46:o.key=a?s.C0.ESC+"[3;"+(a+1)+"~":s.C0.ESC+"[3~";break;case 36:o.key=a?s.C0.ESC+"[1;"+(a+1)+"H":t?s.C0.ESC+"OH":s.C0.ESC+"[H";break;case 35:o.key=a?s.C0.ESC+"[1;"+(a+1)+"F":t?s.C0.ESC+"OF":s.C0.ESC+"[F";break;case 33:e.shiftKey?o.type=2:e.ctrlKey?o.key=s.C0.ESC+"[5;"+(a+1)+"~":o.key=s.C0.ESC+"[5~";break;case 34:e.shiftKey?o.type=3:e.ctrlKey?o.key=s.C0.ESC+"[6;"+(a+1)+"~":o.key=s.C0.ESC+"[6~";break;case 112:o.key=a?s.C0.ESC+"[1;"+(a+1)+"P":s.C0.ESC+"OP";break;case 113:o.key=a?s.C0.ESC+"[1;"+(a+1)+"Q":s.C0.ESC+"OQ";break;case 114:o.key=a?s.C0.ESC+"[1;"+(a+1)+"R":s.C0.ESC+"OR";break;case 115:o.key=a?s.C0.ESC+"[1;"+(a+1)+"S":s.C0.ESC+"OS";break;case 116:o.key=a?s.C0.ESC+"[15;"+(a+1)+"~":s.C0.ESC+"[15~";break;case 117:o.key=a?s.C0.ESC+"[17;"+(a+1)+"~":s.C0.ESC+"[17~";break;case 118:o.key=a?s.C0.ESC+"[18;"+(a+1)+"~":s.C0.ESC+"[18~";break;case 119:o.key=a?s.C0.ESC+"[19;"+(a+1)+"~":s.C0.ESC+"[19~";break;case 120:o.key=a?s.C0.ESC+"[20;"+(a+1)+"~":s.C0.ESC+"[20~";break;case 121:o.key=a?s.C0.ESC+"[21;"+(a+1)+"~":s.C0.ESC+"[21~";break;case 122:o.key=a?s.C0.ESC+"[23;"+(a+1)+"~":s.C0.ESC+"[23~";break;case 123:o.key=a?s.C0.ESC+"[24;"+(a+1)+"~":s.C0.ESC+"[24~";break;default:if(!e.ctrlKey||e.shiftKey||e.altKey||e.metaKey)if(i&&!n||!e.altKey||e.metaKey)!i||e.altKey||e.ctrlKey||e.shiftKey||!e.metaKey?e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&e.keyCode>=48&&1===e.key.length?o.key=e.key:e.key&&e.ctrlKey&&("_"===e.key&&(o.key=s.C0.US),"@"===e.key&&(o.key=s.C0.NUL)):65===e.keyCode&&(o.type=1);else{const t=r[e.keyCode],i=null==t?void 0:t[e.shiftKey?1:0];if(i)o.key=s.C0.ESC+i;else if(e.keyCode>=65&&e.keyCode<=90){const t=e.ctrlKey?e.keyCode-64:e.keyCode+32;let i=String.fromCharCode(t);e.shiftKey&&(i=i.toUpperCase()),o.key=s.C0.ESC+i}else if(32===e.keyCode)o.key=s.C0.ESC+(e.ctrlKey?s.C0.NUL:" ");else if("Dead"===e.key&&e.code.startsWith("Key")){let t=e.code.slice(3,4);e.shiftKey||(t=t.toLowerCase()),o.key=s.C0.ESC+t,o.cancel=!0}}else e.keyCode>=65&&e.keyCode<=90?o.key=String.fromCharCode(e.keyCode-64):32===e.keyCode?o.key=s.C0.NUL:e.keyCode>=51&&e.keyCode<=55?o.key=String.fromCharCode(e.keyCode-51+27):56===e.keyCode?o.key=s.C0.DEL:219===e.keyCode?o.key=s.C0.ESC:220===e.keyCode?o.key=s.C0.FS:221===e.keyCode&&(o.key=s.C0.GS)}return o}},482:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Utf8ToUtf32=t.StringToUtf32=t.utf32ToString=t.stringFromCodePoint=void 0,t.stringFromCodePoint=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10))+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)},t.utf32ToString=function(e,t=0,i=e.length){let s="";for(let r=t;r65535?(t-=65536,s+=String.fromCharCode(55296+(t>>10))+String.fromCharCode(t%1024+56320)):s+=String.fromCharCode(t)}return s},t.StringToUtf32=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){const i=e.length;if(!i)return 0;let s=0,r=0;if(this._interim){const i=e.charCodeAt(r++);56320<=i&&i<=57343?t[s++]=1024*(this._interim-55296)+i-56320+65536:(t[s++]=this._interim,t[s++]=i),this._interim=0}for(let n=r;n=i)return this._interim=r,s;const o=e.charCodeAt(n);56320<=o&&o<=57343?t[s++]=1024*(r-55296)+o-56320+65536:(t[s++]=r,t[s++]=o)}else 65279!==r&&(t[s++]=r)}return s}},t.Utf8ToUtf32=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){const i=e.length;if(!i)return 0;let s,r,n,o,a=0,h=0,c=0;if(this.interim[0]){let s=!1,r=this.interim[0];r&=192==(224&r)?31:224==(240&r)?15:7;let n,o=0;for(;(n=63&this.interim[++o])&&o<4;)r<<=6,r|=n;const h=192==(224&this.interim[0])?2:224==(240&this.interim[0])?3:4,l=h-o;for(;c=i)return 0;if(n=e[c++],128!=(192&n)){c--,s=!0;break}this.interim[o++]=n,r<<=6,r|=63&n}s||(2===h?r<128?c--:t[a++]=r:3===h?r<2048||r>=55296&&r<=57343||65279===r||(t[a++]=r):r<65536||r>1114111||(t[a++]=r)),this.interim.fill(0)}const l=i-4;let d=c;for(;d=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(h=(31&s)<<6|63&r,h<128){d--;continue}t[a++]=h}else if(224==(240&s)){if(d>=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,a;if(n=e[d++],128!=(192&n)){d--;continue}if(h=(15&s)<<12|(63&r)<<6|63&n,h<2048||h>=55296&&h<=57343||65279===h)continue;t[a++]=h}else if(240==(248&s)){if(d>=i)return this.interim[0]=s,a;if(r=e[d++],128!=(192&r)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,a;if(n=e[d++],128!=(192&n)){d--;continue}if(d>=i)return this.interim[0]=s,this.interim[1]=r,this.interim[2]=n,a;if(o=e[d++],128!=(192&o)){d--;continue}if(h=(7&s)<<18|(63&r)<<12|(63&n)<<6|63&o,h<65536||h>1114111)continue;t[a++]=h}}return a}}},225:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV6=void 0;const i=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],s=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];let r;t.UnicodeV6=class{constructor(){if(this.version="6",!r){r=new Uint8Array(65536),r.fill(1),r[0]=0,r.fill(0,1,32),r.fill(0,127,160),r.fill(2,4352,4448),r[9001]=2,r[9002]=2,r.fill(2,11904,42192),r[12351]=1,r.fill(2,44032,55204),r.fill(2,63744,64256),r.fill(2,65040,65050),r.fill(2,65072,65136),r.fill(2,65280,65377),r.fill(2,65504,65511);for(let e=0;et[r][1])return!1;for(;r>=s;)if(i=s+r>>1,e>t[i][1])s=i+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1}}},5981:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WriteBuffer=void 0;const s=i(8460),r=i(844);class n extends r.Disposable{constructor(e){super(),this._action=e,this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0,this._isSyncWriting=!1,this._syncCalls=0,this._didUserInput=!1,this._onWriteParsed=this.register(new s.EventEmitter),this.onWriteParsed=this._onWriteParsed.event}handleUserInput(){this._didUserInput=!0}writeSync(e,t){if(void 0!==t&&this._syncCalls>t)return void(this._syncCalls=0);if(this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(void 0),this._syncCalls++,this._isSyncWriting)return;let i;for(this._isSyncWriting=!0;i=this._writeBuffer.shift();){this._action(i);const e=this._callbacks.shift();e&&e()}this._pendingData=0,this._bufferOffset=2147483647,this._isSyncWriting=!1,this._syncCalls=0}write(e,t){if(this._pendingData>5e7)throw new Error("write data discarded, use flow control to avoid losing data");if(!this._writeBuffer.length){if(this._bufferOffset=0,this._didUserInput)return this._didUserInput=!1,this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t),void this._innerWrite();setTimeout((()=>this._innerWrite()))}this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t)}_innerWrite(e=0,t=!0){const i=e||Date.now();for(;this._writeBuffer.length>this._bufferOffset;){const e=this._writeBuffer[this._bufferOffset],s=this._action(e,t);if(s){const e=e=>Date.now()-i>=12?setTimeout((()=>this._innerWrite(0,e))):this._innerWrite(i,e);return void s.catch((e=>(queueMicrotask((()=>{throw e})),Promise.resolve(!1)))).then(e)}const r=this._callbacks[this._bufferOffset];if(r&&r(),this._bufferOffset++,this._pendingData-=e.length,Date.now()-i>=12)break}this._writeBuffer.length>this._bufferOffset?(this._bufferOffset>50&&(this._writeBuffer=this._writeBuffer.slice(this._bufferOffset),this._callbacks=this._callbacks.slice(this._bufferOffset),this._bufferOffset=0),setTimeout((()=>this._innerWrite()))):(this._writeBuffer.length=0,this._callbacks.length=0,this._pendingData=0,this._bufferOffset=0),this._onWriteParsed.fire()}}t.WriteBuffer=n},5941:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.toRgbString=t.parseColor=void 0;const i=/^([\da-f])\/([\da-f])\/([\da-f])$|^([\da-f]{2})\/([\da-f]{2})\/([\da-f]{2})$|^([\da-f]{3})\/([\da-f]{3})\/([\da-f]{3})$|^([\da-f]{4})\/([\da-f]{4})\/([\da-f]{4})$/,s=/^[\da-f]+$/;function r(e,t){const i=e.toString(16),s=i.length<2?"0"+i:i;switch(t){case 4:return i[0];case 8:return s;case 12:return(s+s).slice(0,3);default:return s+s}}t.parseColor=function(e){if(!e)return;let t=e.toLowerCase();if(0===t.indexOf("rgb:")){t=t.slice(4);const e=i.exec(t);if(e){const t=e[1]?15:e[4]?255:e[7]?4095:65535;return[Math.round(parseInt(e[1]||e[4]||e[7]||e[10],16)/t*255),Math.round(parseInt(e[2]||e[5]||e[8]||e[11],16)/t*255),Math.round(parseInt(e[3]||e[6]||e[9]||e[12],16)/t*255)]}}else if(0===t.indexOf("#")&&(t=t.slice(1),s.exec(t)&&[3,6,9,12].includes(t.length))){const e=t.length/3,i=[0,0,0];for(let s=0;s<3;++s){const r=parseInt(t.slice(e*s,e*s+e),16);i[s]=1===e?r<<4:2===e?r:3===e?r>>4:r>>8}return i}},t.toRgbString=function(e,t=16){const[i,s,n]=e;return`rgb:${r(i,t)}/${r(s,t)}/${r(n,t)}`}},5770:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.PAYLOAD_LIMIT=void 0,t.PAYLOAD_LIMIT=1e7},6351:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DcsHandler=t.DcsParser=void 0;const s=i(482),r=i(8742),n=i(5770),o=[];t.DcsParser=class{constructor(){this._handlers=Object.create(null),this._active=o,this._ident=0,this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=o}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const i=this._handlers[e];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}reset(){if(this._active.length)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].unhook(!1);this._stack.paused=!1,this._active=o,this._ident=0}hook(e,t){if(this.reset(),this._ident=e,this._active=this._handlers[e]||o,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].hook(t);else this._handlerFb(this._ident,"HOOK",t)}put(e,t,i){if(this._active.length)for(let s=this._active.length-1;s>=0;s--)this._active[s].put(e,t,i);else this._handlerFb(this._ident,"PUT",(0,s.utf32ToString)(e,t,i))}unhook(e,t=!0){if(this._active.length){let i=!1,s=this._active.length-1,r=!1;if(this._stack.paused&&(s=this._stack.loopPosition-1,i=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===i){for(;s>=0&&(i=this._active[s].unhook(e),!0!==i);s--)if(i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!1,i;s--}for(;s>=0;s--)if(i=this._active[s].unhook(!1),i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!0,i}else this._handlerFb(this._ident,"UNHOOK",e);this._active=o,this._ident=0}};const a=new r.Params;a.addParam(0),t.DcsHandler=class{constructor(e){this._handler=e,this._data="",this._params=a,this._hitLimit=!1}hook(e){this._params=e.length>1||e.params[0]?e.clone():a,this._data="",this._hitLimit=!1}put(e,t,i){this._hitLimit||(this._data+=(0,s.utf32ToString)(e,t,i),this._data.length>n.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}unhook(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data,this._params),t instanceof Promise))return t.then((e=>(this._params=a,this._data="",this._hitLimit=!1,e)));return this._params=a,this._data="",this._hitLimit=!1,t}}},2015:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.EscapeSequenceParser=t.VT500_TRANSITION_TABLE=t.TransitionTable=void 0;const s=i(844),r=i(8742),n=i(6242),o=i(6351);class a{constructor(e){this.table=new Uint8Array(e)}setDefault(e,t){this.table.fill(e<<4|t)}add(e,t,i,s){this.table[t<<8|e]=i<<4|s}addMany(e,t,i,s){for(let r=0;rt)),i=(e,i)=>t.slice(e,i),s=i(32,127),r=i(0,24);r.push(25),r.push.apply(r,i(28,32));const n=i(0,14);let o;for(o in e.setDefault(1,0),e.addMany(s,0,2,0),n)e.addMany([24,26,153,154],o,3,0),e.addMany(i(128,144),o,3,0),e.addMany(i(144,152),o,3,0),e.add(156,o,0,0),e.add(27,o,11,1),e.add(157,o,4,8),e.addMany([152,158,159],o,0,7),e.add(155,o,11,3),e.add(144,o,11,9);return e.addMany(r,0,3,0),e.addMany(r,1,3,1),e.add(127,1,0,1),e.addMany(r,8,0,8),e.addMany(r,3,3,3),e.add(127,3,0,3),e.addMany(r,4,3,4),e.add(127,4,0,4),e.addMany(r,6,3,6),e.addMany(r,5,3,5),e.add(127,5,0,5),e.addMany(r,2,3,2),e.add(127,2,0,2),e.add(93,1,4,8),e.addMany(s,8,5,8),e.add(127,8,5,8),e.addMany([156,27,24,26,7],8,6,0),e.addMany(i(28,32),8,0,8),e.addMany([88,94,95],1,0,7),e.addMany(s,7,0,7),e.addMany(r,7,0,7),e.add(156,7,0,0),e.add(127,7,0,7),e.add(91,1,11,3),e.addMany(i(64,127),3,7,0),e.addMany(i(48,60),3,8,4),e.addMany([60,61,62,63],3,9,4),e.addMany(i(48,60),4,8,4),e.addMany(i(64,127),4,7,0),e.addMany([60,61,62,63],4,0,6),e.addMany(i(32,64),6,0,6),e.add(127,6,0,6),e.addMany(i(64,127),6,0,0),e.addMany(i(32,48),3,9,5),e.addMany(i(32,48),5,9,5),e.addMany(i(48,64),5,0,6),e.addMany(i(64,127),5,7,0),e.addMany(i(32,48),4,9,5),e.addMany(i(32,48),1,9,2),e.addMany(i(32,48),2,9,2),e.addMany(i(48,127),2,10,0),e.addMany(i(48,80),1,10,0),e.addMany(i(81,88),1,10,0),e.addMany([89,90,92],1,10,0),e.addMany(i(96,127),1,10,0),e.add(80,1,11,9),e.addMany(r,9,0,9),e.add(127,9,0,9),e.addMany(i(28,32),9,0,9),e.addMany(i(32,48),9,9,12),e.addMany(i(48,60),9,8,10),e.addMany([60,61,62,63],9,9,10),e.addMany(r,11,0,11),e.addMany(i(32,128),11,0,11),e.addMany(i(28,32),11,0,11),e.addMany(r,10,0,10),e.add(127,10,0,10),e.addMany(i(28,32),10,0,10),e.addMany(i(48,60),10,8,10),e.addMany([60,61,62,63],10,0,11),e.addMany(i(32,48),10,9,12),e.addMany(r,12,0,12),e.add(127,12,0,12),e.addMany(i(28,32),12,0,12),e.addMany(i(32,48),12,9,12),e.addMany(i(48,64),12,0,11),e.addMany(i(64,127),12,12,13),e.addMany(i(64,127),10,12,13),e.addMany(i(64,127),9,12,13),e.addMany(r,13,13,13),e.addMany(s,13,13,13),e.add(127,13,0,13),e.addMany([27,156,24,26],13,14,0),e.add(h,0,2,0),e.add(h,8,5,8),e.add(h,6,0,6),e.add(h,11,0,11),e.add(h,13,13,13),e}();class c extends s.Disposable{constructor(e=t.VT500_TRANSITION_TABLE){super(),this._transitions=e,this._parseStack={state:0,handlers:[],handlerPos:0,transition:0,chunkPos:0},this.initialState=0,this.currentState=this.initialState,this._params=new r.Params,this._params.addParam(0),this._collect=0,this.precedingCodepoint=0,this._printHandlerFb=(e,t,i)=>{},this._executeHandlerFb=e=>{},this._csiHandlerFb=(e,t)=>{},this._escHandlerFb=e=>{},this._errorHandlerFb=e=>e,this._printHandler=this._printHandlerFb,this._executeHandlers=Object.create(null),this._csiHandlers=Object.create(null),this._escHandlers=Object.create(null),this.register((0,s.toDisposable)((()=>{this._csiHandlers=Object.create(null),this._executeHandlers=Object.create(null),this._escHandlers=Object.create(null)}))),this._oscParser=this.register(new n.OscParser),this._dcsParser=this.register(new o.DcsParser),this._errorHandler=this._errorHandlerFb,this.registerEscHandler({final:"\\"},(()=>!0))}_identifier(e,t=[64,126]){let i=0;if(e.prefix){if(e.prefix.length>1)throw new Error("only one byte as prefix supported");if(i=e.prefix.charCodeAt(0),i&&60>i||i>63)throw new Error("prefix must be in range 0x3c .. 0x3f")}if(e.intermediates){if(e.intermediates.length>2)throw new Error("only two bytes as intermediates are supported");for(let t=0;ts||s>47)throw new Error("intermediate must be in range 0x20 .. 0x2f");i<<=8,i|=s}}if(1!==e.final.length)throw new Error("final must be a single byte");const s=e.final.charCodeAt(0);if(t[0]>s||s>t[1])throw new Error(`final must be in range ${t[0]} .. ${t[1]}`);return i<<=8,i|=s,i}identToString(e){const t=[];for(;e;)t.push(String.fromCharCode(255&e)),e>>=8;return t.reverse().join("")}setPrintHandler(e){this._printHandler=e}clearPrintHandler(){this._printHandler=this._printHandlerFb}registerEscHandler(e,t){const i=this._identifier(e,[48,126]);void 0===this._escHandlers[i]&&(this._escHandlers[i]=[]);const s=this._escHandlers[i];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearEscHandler(e){this._escHandlers[this._identifier(e,[48,126])]&&delete this._escHandlers[this._identifier(e,[48,126])]}setEscHandlerFallback(e){this._escHandlerFb=e}setExecuteHandler(e,t){this._executeHandlers[e.charCodeAt(0)]=t}clearExecuteHandler(e){this._executeHandlers[e.charCodeAt(0)]&&delete this._executeHandlers[e.charCodeAt(0)]}setExecuteHandlerFallback(e){this._executeHandlerFb=e}registerCsiHandler(e,t){const i=this._identifier(e);void 0===this._csiHandlers[i]&&(this._csiHandlers[i]=[]);const s=this._csiHandlers[i];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearCsiHandler(e){this._csiHandlers[this._identifier(e)]&&delete this._csiHandlers[this._identifier(e)]}setCsiHandlerFallback(e){this._csiHandlerFb=e}registerDcsHandler(e,t){return this._dcsParser.registerHandler(this._identifier(e),t)}clearDcsHandler(e){this._dcsParser.clearHandler(this._identifier(e))}setDcsHandlerFallback(e){this._dcsParser.setHandlerFallback(e)}registerOscHandler(e,t){return this._oscParser.registerHandler(e,t)}clearOscHandler(e){this._oscParser.clearHandler(e)}setOscHandlerFallback(e){this._oscParser.setHandlerFallback(e)}setErrorHandler(e){this._errorHandler=e}clearErrorHandler(){this._errorHandler=this._errorHandlerFb}reset(){this.currentState=this.initialState,this._oscParser.reset(),this._dcsParser.reset(),this._params.reset(),this._params.addParam(0),this._collect=0,this.precedingCodepoint=0,0!==this._parseStack.state&&(this._parseStack.state=2,this._parseStack.handlers=[])}_preserveStack(e,t,i,s,r){this._parseStack.state=e,this._parseStack.handlers=t,this._parseStack.handlerPos=i,this._parseStack.transition=s,this._parseStack.chunkPos=r}parse(e,t,i){let s,r=0,n=0,o=0;if(this._parseStack.state)if(2===this._parseStack.state)this._parseStack.state=0,o=this._parseStack.chunkPos+1;else{if(void 0===i||1===this._parseStack.state)throw this._parseStack.state=1,new Error("improper continuation due to previous async handler, giving up parsing");const t=this._parseStack.handlers;let n=this._parseStack.handlerPos-1;switch(this._parseStack.state){case 3:if(!1===i&&n>-1)for(;n>=0&&(s=t[n](this._params),!0!==s);n--)if(s instanceof Promise)return this._parseStack.handlerPos=n,s;this._parseStack.handlers=[];break;case 4:if(!1===i&&n>-1)for(;n>=0&&(s=t[n](),!0!==s);n--)if(s instanceof Promise)return this._parseStack.handlerPos=n,s;this._parseStack.handlers=[];break;case 6:if(r=e[this._parseStack.chunkPos],s=this._dcsParser.unhook(24!==r&&26!==r,i),s)return s;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0;break;case 5:if(r=e[this._parseStack.chunkPos],s=this._oscParser.end(24!==r&&26!==r,i),s)return s;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0}this._parseStack.state=0,o=this._parseStack.chunkPos+1,this.precedingCodepoint=0,this.currentState=15&this._parseStack.transition}for(let i=o;i>4){case 2:for(let s=i+1;;++s){if(s>=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=t||(r=e[s])<32||r>126&&r=0&&(s=o[a](this._params),!0!==s);a--)if(s instanceof Promise)return this._preserveStack(3,o,a,n,i),s;a<0&&this._csiHandlerFb(this._collect<<8|r,this._params),this.precedingCodepoint=0;break;case 8:do{switch(r){case 59:this._params.addParam(0);break;case 58:this._params.addSubParam(-1);break;default:this._params.addDigit(r-48)}}while(++i47&&r<60);i--;break;case 9:this._collect<<=8,this._collect|=r;break;case 10:const c=this._escHandlers[this._collect<<8|r];let l=c?c.length-1:-1;for(;l>=0&&(s=c[l](),!0!==s);l--)if(s instanceof Promise)return this._preserveStack(4,c,l,n,i),s;l<0&&this._escHandlerFb(this._collect<<8|r),this.precedingCodepoint=0;break;case 11:this._params.reset(),this._params.addParam(0),this._collect=0;break;case 12:this._dcsParser.hook(this._collect<<8|r,this._params);break;case 13:for(let s=i+1;;++s)if(s>=t||24===(r=e[s])||26===r||27===r||r>127&&r=t||(r=e[s])<32||r>127&&r{Object.defineProperty(t,"__esModule",{value:!0}),t.OscHandler=t.OscParser=void 0;const s=i(5770),r=i(482),n=[];t.OscParser=class{constructor(){this._state=0,this._active=n,this._id=-1,this._handlers=Object.create(null),this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const i=this._handlers[e];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=n}reset(){if(2===this._state)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].end(!1);this._stack.paused=!1,this._active=n,this._id=-1,this._state=0}_start(){if(this._active=this._handlers[this._id]||n,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].start();else this._handlerFb(this._id,"START")}_put(e,t,i){if(this._active.length)for(let s=this._active.length-1;s>=0;s--)this._active[s].put(e,t,i);else this._handlerFb(this._id,"PUT",(0,r.utf32ToString)(e,t,i))}start(){this.reset(),this._state=1}put(e,t,i){if(3!==this._state){if(1===this._state)for(;t0&&this._put(e,t,i)}}end(e,t=!0){if(0!==this._state){if(3!==this._state)if(1===this._state&&this._start(),this._active.length){let i=!1,s=this._active.length-1,r=!1;if(this._stack.paused&&(s=this._stack.loopPosition-1,i=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===i){for(;s>=0&&(i=this._active[s].end(e),!0!==i);s--)if(i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!1,i;s--}for(;s>=0;s--)if(i=this._active[s].end(!1),i instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=s,this._stack.fallThrough=!0,i}else this._handlerFb(this._id,"END",e);this._active=n,this._id=-1,this._state=0}}},t.OscHandler=class{constructor(e){this._handler=e,this._data="",this._hitLimit=!1}start(){this._data="",this._hitLimit=!1}put(e,t,i){this._hitLimit||(this._data+=(0,r.utf32ToString)(e,t,i),this._data.length>s.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}end(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data),t instanceof Promise))return t.then((e=>(this._data="",this._hitLimit=!1,e)));return this._data="",this._hitLimit=!1,t}}},8742:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Params=void 0;const i=2147483647;class s{static fromArray(e){const t=new s;if(!e.length)return t;for(let i=Array.isArray(e[0])?1:0;i256)throw new Error("maxSubParamsLength must not be greater than 256");this.params=new Int32Array(e),this.length=0,this._subParams=new Int32Array(t),this._subParamsLength=0,this._subParamsIdx=new Uint16Array(e),this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}clone(){const e=new s(this.maxLength,this.maxSubParamsLength);return e.params.set(this.params),e.length=this.length,e._subParams.set(this._subParams),e._subParamsLength=this._subParamsLength,e._subParamsIdx.set(this._subParamsIdx),e._rejectDigits=this._rejectDigits,e._rejectSubDigits=this._rejectSubDigits,e._digitIsSub=this._digitIsSub,e}toArray(){const e=[];for(let t=0;t>8,s=255&this._subParamsIdx[t];s-i>0&&e.push(Array.prototype.slice.call(this._subParams,i,s))}return e}reset(){this.length=0,this._subParamsLength=0,this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}addParam(e){if(this._digitIsSub=!1,this.length>=this.maxLength)this._rejectDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParamsIdx[this.length]=this._subParamsLength<<8|this._subParamsLength,this.params[this.length++]=e>i?i:e}}addSubParam(e){if(this._digitIsSub=!0,this.length)if(this._rejectDigits||this._subParamsLength>=this.maxSubParamsLength)this._rejectSubDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParams[this._subParamsLength++]=e>i?i:e,this._subParamsIdx[this.length-1]++}}hasSubParams(e){return(255&this._subParamsIdx[e])-(this._subParamsIdx[e]>>8)>0}getSubParams(e){const t=this._subParamsIdx[e]>>8,i=255&this._subParamsIdx[e];return i-t>0?this._subParams.subarray(t,i):null}getSubParamsAll(){const e={};for(let t=0;t>8,s=255&this._subParamsIdx[t];s-i>0&&(e[t]=this._subParams.slice(i,s))}return e}addDigit(e){let t;if(this._rejectDigits||!(t=this._digitIsSub?this._subParamsLength:this.length)||this._digitIsSub&&this._rejectSubDigits)return;const s=this._digitIsSub?this._subParams:this.params,r=s[t-1];s[t-1]=~r?Math.min(10*r+e,i):e}}t.Params=s},5741:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AddonManager=void 0,t.AddonManager=class{constructor(){this._addons=[]}dispose(){for(let e=this._addons.length-1;e>=0;e--)this._addons[e].instance.dispose()}loadAddon(e,t){const i={instance:t,dispose:t.dispose,isDisposed:!1};this._addons.push(i),t.dispose=()=>this._wrappedAddonDispose(i),t.activate(e)}_wrappedAddonDispose(e){if(e.isDisposed)return;let t=-1;for(let i=0;i{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferApiView=void 0;const s=i(3785),r=i(511);t.BufferApiView=class{constructor(e,t){this._buffer=e,this.type=t}init(e){return this._buffer=e,this}get cursorY(){return this._buffer.y}get cursorX(){return this._buffer.x}get viewportY(){return this._buffer.ydisp}get baseY(){return this._buffer.ybase}get length(){return this._buffer.lines.length}getLine(e){const t=this._buffer.lines.get(e);if(t)return new s.BufferLineApiView(t)}getNullCell(){return new r.CellData}}},3785:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLineApiView=void 0;const s=i(511);t.BufferLineApiView=class{constructor(e){this._line=e}get isWrapped(){return this._line.isWrapped}get length(){return this._line.length}getCell(e,t){if(!(e<0||e>=this._line.length))return t?(this._line.loadCell(e,t),t):this._line.loadCell(e,new s.CellData)}translateToString(e,t,i){return this._line.translateToString(e,t,i)}}},8285:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferNamespaceApi=void 0;const s=i(8771),r=i(8460),n=i(844);class o extends n.Disposable{constructor(e){super(),this._core=e,this._onBufferChange=this.register(new r.EventEmitter),this.onBufferChange=this._onBufferChange.event,this._normal=new s.BufferApiView(this._core.buffers.normal,"normal"),this._alternate=new s.BufferApiView(this._core.buffers.alt,"alternate"),this._core.buffers.onBufferActivate((()=>this._onBufferChange.fire(this.active)))}get active(){if(this._core.buffers.active===this._core.buffers.normal)return this.normal;if(this._core.buffers.active===this._core.buffers.alt)return this.alternate;throw new Error("Active buffer is neither normal nor alternate")}get normal(){return this._normal.init(this._core.buffers.normal)}get alternate(){return this._alternate.init(this._core.buffers.alt)}}t.BufferNamespaceApi=o},7975:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ParserApi=void 0,t.ParserApi=class{constructor(e){this._core=e}registerCsiHandler(e,t){return this._core.registerCsiHandler(e,(e=>t(e.toArray())))}addCsiHandler(e,t){return this.registerCsiHandler(e,t)}registerDcsHandler(e,t){return this._core.registerDcsHandler(e,((e,i)=>t(e,i.toArray())))}addDcsHandler(e,t){return this.registerDcsHandler(e,t)}registerEscHandler(e,t){return this._core.registerEscHandler(e,t)}addEscHandler(e,t){return this.registerEscHandler(e,t)}registerOscHandler(e,t){return this._core.registerOscHandler(e,t)}addOscHandler(e,t){return this.registerOscHandler(e,t)}}},7090:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeApi=void 0,t.UnicodeApi=class{constructor(e){this._core=e}register(e){this._core.unicodeService.register(e)}get versions(){return this._core.unicodeService.versions}get activeVersion(){return this._core.unicodeService.activeVersion}set activeVersion(e){this._core.unicodeService.activeVersion=e}}},744:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferService=t.MINIMUM_ROWS=t.MINIMUM_COLS=void 0;const n=i(8460),o=i(844),a=i(5295),h=i(2585);t.MINIMUM_COLS=2,t.MINIMUM_ROWS=1;let c=t.BufferService=class extends o.Disposable{get buffer(){return this.buffers.active}constructor(e){super(),this.isUserScrolling=!1,this._onResize=this.register(new n.EventEmitter),this.onResize=this._onResize.event,this._onScroll=this.register(new n.EventEmitter),this.onScroll=this._onScroll.event,this.cols=Math.max(e.rawOptions.cols||0,t.MINIMUM_COLS),this.rows=Math.max(e.rawOptions.rows||0,t.MINIMUM_ROWS),this.buffers=this.register(new a.BufferSet(e,this))}resize(e,t){this.cols=e,this.rows=t,this.buffers.resize(e,t),this._onResize.fire({cols:e,rows:t})}reset(){this.buffers.reset(),this.isUserScrolling=!1}scroll(e,t=!1){const i=this.buffer;let s;s=this._cachedBlankLine,s&&s.length===this.cols&&s.getFg(0)===e.fg&&s.getBg(0)===e.bg||(s=i.getBlankLine(e,t),this._cachedBlankLine=s),s.isWrapped=t;const r=i.ybase+i.scrollTop,n=i.ybase+i.scrollBottom;if(0===i.scrollTop){const e=i.lines.isFull;n===i.lines.length-1?e?i.lines.recycle().copyFrom(s):i.lines.push(s.clone()):i.lines.splice(n+1,0,s.clone()),e?this.isUserScrolling&&(i.ydisp=Math.max(i.ydisp-1,0)):(i.ybase++,this.isUserScrolling||i.ydisp++)}else{const e=n-r+1;i.lines.shiftElements(r+1,e-1,-1),i.lines.set(n,s.clone())}this.isUserScrolling||(i.ydisp=i.ybase),this._onScroll.fire(i.ydisp)}scrollLines(e,t,i){const s=this.buffer;if(e<0){if(0===s.ydisp)return;this.isUserScrolling=!0}else e+s.ydisp>=s.ybase&&(this.isUserScrolling=!1);const r=s.ydisp;s.ydisp=Math.max(Math.min(s.ydisp+e,s.ybase),0),r!==s.ydisp&&(t||this._onScroll.fire(s.ydisp))}};t.BufferService=c=s([r(0,h.IOptionsService)],c)},7994:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CharsetService=void 0,t.CharsetService=class{constructor(){this.glevel=0,this._charsets=[]}reset(){this.charset=void 0,this._charsets=[],this.glevel=0}setgLevel(e){this.glevel=e,this.charset=this._charsets[e]}setgCharset(e,t){this._charsets[e]=t,this.glevel===e&&(this.charset=t)}}},1753:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreMouseService=void 0;const n=i(2585),o=i(8460),a=i(844),h={NONE:{events:0,restrict:()=>!1},X10:{events:1,restrict:e=>4!==e.button&&1===e.action&&(e.ctrl=!1,e.alt=!1,e.shift=!1,!0)},VT200:{events:19,restrict:e=>32!==e.action},DRAG:{events:23,restrict:e=>32!==e.action||3!==e.button},ANY:{events:31,restrict:e=>!0}};function c(e,t){let i=(e.ctrl?16:0)|(e.shift?4:0)|(e.alt?8:0);return 4===e.button?(i|=64,i|=e.action):(i|=3&e.button,4&e.button&&(i|=64),8&e.button&&(i|=128),32===e.action?i|=32:0!==e.action||t||(i|=3)),i}const l=String.fromCharCode,d={DEFAULT:e=>{const t=[c(e,!1)+32,e.col+32,e.row+32];return t[0]>255||t[1]>255||t[2]>255?"":`${l(t[0])}${l(t[1])}${l(t[2])}`},SGR:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.col};${e.row}${t}`},SGR_PIXELS:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.x};${e.y}${t}`}};let _=t.CoreMouseService=class extends a.Disposable{constructor(e,t){super(),this._bufferService=e,this._coreService=t,this._protocols={},this._encodings={},this._activeProtocol="",this._activeEncoding="",this._lastEvent=null,this._onProtocolChange=this.register(new o.EventEmitter),this.onProtocolChange=this._onProtocolChange.event;for(const e of Object.keys(h))this.addProtocol(e,h[e]);for(const e of Object.keys(d))this.addEncoding(e,d[e]);this.reset()}addProtocol(e,t){this._protocols[e]=t}addEncoding(e,t){this._encodings[e]=t}get activeProtocol(){return this._activeProtocol}get areMouseEventsActive(){return 0!==this._protocols[this._activeProtocol].events}set activeProtocol(e){if(!this._protocols[e])throw new Error(`unknown protocol "${e}"`);this._activeProtocol=e,this._onProtocolChange.fire(this._protocols[e].events)}get activeEncoding(){return this._activeEncoding}set activeEncoding(e){if(!this._encodings[e])throw new Error(`unknown encoding "${e}"`);this._activeEncoding=e}reset(){this.activeProtocol="NONE",this.activeEncoding="DEFAULT",this._lastEvent=null}triggerMouseEvent(e){if(e.col<0||e.col>=this._bufferService.cols||e.row<0||e.row>=this._bufferService.rows)return!1;if(4===e.button&&32===e.action)return!1;if(3===e.button&&32!==e.action)return!1;if(4!==e.button&&(2===e.action||3===e.action))return!1;if(e.col++,e.row++,32===e.action&&this._lastEvent&&this._equalEvents(this._lastEvent,e,"SGR_PIXELS"===this._activeEncoding))return!1;if(!this._protocols[this._activeProtocol].restrict(e))return!1;const t=this._encodings[this._activeEncoding](e);return t&&("DEFAULT"===this._activeEncoding?this._coreService.triggerBinaryEvent(t):this._coreService.triggerDataEvent(t,!0)),this._lastEvent=e,!0}explainEvents(e){return{down:!!(1&e),up:!!(2&e),drag:!!(4&e),move:!!(8&e),wheel:!!(16&e)}}_equalEvents(e,t,i){if(i){if(e.x!==t.x)return!1;if(e.y!==t.y)return!1}else{if(e.col!==t.col)return!1;if(e.row!==t.row)return!1}return e.button===t.button&&e.action===t.action&&e.ctrl===t.ctrl&&e.alt===t.alt&&e.shift===t.shift}};t.CoreMouseService=_=s([r(0,n.IBufferService),r(1,n.ICoreService)],_)},6975:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreService=void 0;const n=i(1439),o=i(8460),a=i(844),h=i(2585),c=Object.freeze({insertMode:!1}),l=Object.freeze({applicationCursorKeys:!1,applicationKeypad:!1,bracketedPasteMode:!1,origin:!1,reverseWraparound:!1,sendFocus:!1,wraparound:!0});let d=t.CoreService=class extends a.Disposable{constructor(e,t,i){super(),this._bufferService=e,this._logService=t,this._optionsService=i,this.isCursorInitialized=!1,this.isCursorHidden=!1,this._onData=this.register(new o.EventEmitter),this.onData=this._onData.event,this._onUserInput=this.register(new o.EventEmitter),this.onUserInput=this._onUserInput.event,this._onBinary=this.register(new o.EventEmitter),this.onBinary=this._onBinary.event,this._onRequestScrollToBottom=this.register(new o.EventEmitter),this.onRequestScrollToBottom=this._onRequestScrollToBottom.event,this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}reset(){this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}triggerDataEvent(e,t=!1){if(this._optionsService.rawOptions.disableStdin)return;const i=this._bufferService.buffer;t&&this._optionsService.rawOptions.scrollOnUserInput&&i.ybase!==i.ydisp&&this._onRequestScrollToBottom.fire(),t&&this._onUserInput.fire(),this._logService.debug(`sending data "${e}"`,(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onData.fire(e)}triggerBinaryEvent(e){this._optionsService.rawOptions.disableStdin||(this._logService.debug(`sending binary "${e}"`,(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onBinary.fire(e))}};t.CoreService=d=s([r(0,h.IBufferService),r(1,h.ILogService),r(2,h.IOptionsService)],d)},9074:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationService=void 0;const s=i(8055),r=i(8460),n=i(844),o=i(6106);let a=0,h=0;class c extends n.Disposable{get decorations(){return this._decorations.values()}constructor(){super(),this._decorations=new o.SortedList((e=>null==e?void 0:e.marker.line)),this._onDecorationRegistered=this.register(new r.EventEmitter),this.onDecorationRegistered=this._onDecorationRegistered.event,this._onDecorationRemoved=this.register(new r.EventEmitter),this.onDecorationRemoved=this._onDecorationRemoved.event,this.register((0,n.toDisposable)((()=>this.reset())))}registerDecoration(e){if(e.marker.isDisposed)return;const t=new l(e);if(t){const e=t.marker.onDispose((()=>t.dispose()));t.onDispose((()=>{t&&(this._decorations.delete(t)&&this._onDecorationRemoved.fire(t),e.dispose())})),this._decorations.insert(t),this._onDecorationRegistered.fire(t)}return t}reset(){for(const e of this._decorations.values())e.dispose();this._decorations.clear()}*getDecorationsAtCell(e,t,i){var s,r,n;let o=0,a=0;for(const h of this._decorations.getKeyIterator(t))o=null!==(s=h.options.x)&&void 0!==s?s:0,a=o+(null!==(r=h.options.width)&&void 0!==r?r:1),e>=o&&e{var r,n,o;a=null!==(r=t.options.x)&&void 0!==r?r:0,h=a+(null!==(n=t.options.width)&&void 0!==n?n:1),e>=a&&e{Object.defineProperty(t,"__esModule",{value:!0}),t.InstantiationService=t.ServiceCollection=void 0;const s=i(2585),r=i(8343);class n{constructor(...e){this._entries=new Map;for(const[t,i]of e)this.set(t,i)}set(e,t){const i=this._entries.get(e);return this._entries.set(e,t),i}forEach(e){for(const[t,i]of this._entries.entries())e(t,i)}has(e){return this._entries.has(e)}get(e){return this._entries.get(e)}}t.ServiceCollection=n,t.InstantiationService=class{constructor(){this._services=new n,this._services.set(s.IInstantiationService,this)}setService(e,t){this._services.set(e,t)}getService(e){return this._services.get(e)}createInstance(e,...t){const i=(0,r.getServiceDependencies)(e).sort(((e,t)=>e.index-t.index)),s=[];for(const t of i){const i=this._services.get(t.id);if(!i)throw new Error(`[createInstance] ${e.name} depends on UNKNOWN service ${t.id}.`);s.push(i)}const n=i.length>0?i[0].index:t.length;if(t.length!==n)throw new Error(`[createInstance] First service dependency of ${e.name} at position ${n+1} conflicts with ${t.length} static arguments`);return new e(...[...t,...s])}}},7866:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.traceCall=t.setTraceLogger=t.LogService=void 0;const n=i(844),o=i(2585),a={trace:o.LogLevelEnum.TRACE,debug:o.LogLevelEnum.DEBUG,info:o.LogLevelEnum.INFO,warn:o.LogLevelEnum.WARN,error:o.LogLevelEnum.ERROR,off:o.LogLevelEnum.OFF};let h,c=t.LogService=class extends n.Disposable{get logLevel(){return this._logLevel}constructor(e){super(),this._optionsService=e,this._logLevel=o.LogLevelEnum.OFF,this._updateLogLevel(),this.register(this._optionsService.onSpecificOptionChange("logLevel",(()=>this._updateLogLevel()))),h=this}_updateLogLevel(){this._logLevel=a[this._optionsService.rawOptions.logLevel]}_evalLazyOptionalParams(e){for(let t=0;tJSON.stringify(e))).join(", ")})`);const t=s.apply(this,e);return h.trace(`GlyphRenderer#${s.name} return`,t),t}}},7302:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.OptionsService=t.DEFAULT_OPTIONS=void 0;const s=i(8460),r=i(844),n=i(6114);t.DEFAULT_OPTIONS={cols:80,rows:24,cursorBlink:!1,cursorStyle:"block",cursorWidth:1,cursorInactiveStyle:"outline",customGlyphs:!0,drawBoldTextInBrightColors:!0,fastScrollModifier:"alt",fastScrollSensitivity:5,fontFamily:"courier-new, courier, monospace",fontSize:15,fontWeight:"normal",fontWeightBold:"bold",ignoreBracketedPasteMode:!1,lineHeight:1,letterSpacing:0,linkHandler:null,logLevel:"info",logger:null,scrollback:1e3,scrollOnUserInput:!0,scrollSensitivity:1,screenReaderMode:!1,smoothScrollDuration:0,macOptionIsMeta:!1,macOptionClickForcesSelection:!1,minimumContrastRatio:1,disableStdin:!1,allowProposedApi:!1,allowTransparency:!1,tabStopWidth:8,theme:{},rightClickSelectsWord:n.isMac,windowOptions:{},windowsMode:!1,windowsPty:{},wordSeparator:" ()[]{}',\"`",altClickMovesCursor:!0,convertEol:!1,termName:"xterm",cancelEvents:!1,overviewRulerWidth:0};const o=["normal","bold","100","200","300","400","500","600","700","800","900"];class a extends r.Disposable{constructor(e){super(),this._onOptionChange=this.register(new s.EventEmitter),this.onOptionChange=this._onOptionChange.event;const i=Object.assign({},t.DEFAULT_OPTIONS);for(const t in e)if(t in i)try{const s=e[t];i[t]=this._sanitizeAndValidateOption(t,s)}catch(e){console.error(e)}this.rawOptions=i,this.options=Object.assign({},i),this._setupOptions()}onSpecificOptionChange(e,t){return this.onOptionChange((i=>{i===e&&t(this.rawOptions[e])}))}onMultipleOptionChange(e,t){return this.onOptionChange((i=>{-1!==e.indexOf(i)&&t()}))}_setupOptions(){const e=e=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);return this.rawOptions[e]},i=(e,i)=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);i=this._sanitizeAndValidateOption(e,i),this.rawOptions[e]!==i&&(this.rawOptions[e]=i,this._onOptionChange.fire(e))};for(const t in this.rawOptions){const s={get:e.bind(this,t),set:i.bind(this,t)};Object.defineProperty(this.options,t,s)}}_sanitizeAndValidateOption(e,i){switch(e){case"cursorStyle":if(i||(i=t.DEFAULT_OPTIONS[e]),!function(e){return"block"===e||"underline"===e||"bar"===e}(i))throw new Error(`"${i}" is not a valid value for ${e}`);break;case"wordSeparator":i||(i=t.DEFAULT_OPTIONS[e]);break;case"fontWeight":case"fontWeightBold":if("number"==typeof i&&1<=i&&i<=1e3)break;i=o.includes(i)?i:t.DEFAULT_OPTIONS[e];break;case"cursorWidth":i=Math.floor(i);case"lineHeight":case"tabStopWidth":if(i<1)throw new Error(`${e} cannot be less than 1, value: ${i}`);break;case"minimumContrastRatio":i=Math.max(1,Math.min(21,Math.round(10*i)/10));break;case"scrollback":if((i=Math.min(i,4294967295))<0)throw new Error(`${e} cannot be less than 0, value: ${i}`);break;case"fastScrollSensitivity":case"scrollSensitivity":if(i<=0)throw new Error(`${e} cannot be less than or equal to 0, value: ${i}`);break;case"rows":case"cols":if(!i&&0!==i)throw new Error(`${e} must be numeric, value: ${i}`);break;case"windowsPty":i=null!=i?i:{}}return i}}t.OptionsService=a},2660:function(e,t,i){var s=this&&this.__decorate||function(e,t,i,s){var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,s);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},r=this&&this.__param||function(e,t){return function(i,s){t(i,s,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkService=void 0;const n=i(2585);let o=t.OscLinkService=class{constructor(e){this._bufferService=e,this._nextId=1,this._entriesWithId=new Map,this._dataByLinkId=new Map}registerLink(e){const t=this._bufferService.buffer;if(void 0===e.id){const i=t.addMarker(t.ybase+t.y),s={data:e,id:this._nextId++,lines:[i]};return i.onDispose((()=>this._removeMarkerFromLink(s,i))),this._dataByLinkId.set(s.id,s),s.id}const i=e,s=this._getEntryIdKey(i),r=this._entriesWithId.get(s);if(r)return this.addLineToLink(r.id,t.ybase+t.y),r.id;const n=t.addMarker(t.ybase+t.y),o={id:this._nextId++,key:this._getEntryIdKey(i),data:i,lines:[n]};return n.onDispose((()=>this._removeMarkerFromLink(o,n))),this._entriesWithId.set(o.key,o),this._dataByLinkId.set(o.id,o),o.id}addLineToLink(e,t){const i=this._dataByLinkId.get(e);if(i&&i.lines.every((e=>e.line!==t))){const e=this._bufferService.buffer.addMarker(t);i.lines.push(e),e.onDispose((()=>this._removeMarkerFromLink(i,e)))}}getLinkData(e){var t;return null===(t=this._dataByLinkId.get(e))||void 0===t?void 0:t.data}_getEntryIdKey(e){return`${e.id};;${e.uri}`}_removeMarkerFromLink(e,t){const i=e.lines.indexOf(t);-1!==i&&(e.lines.splice(i,1),0===e.lines.length&&(void 0!==e.data.id&&this._entriesWithId.delete(e.key),this._dataByLinkId.delete(e.id)))}};t.OscLinkService=o=s([r(0,n.IBufferService)],o)},8343:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createDecorator=t.getServiceDependencies=t.serviceRegistry=void 0;const i="di$target",s="di$dependencies";t.serviceRegistry=new Map,t.getServiceDependencies=function(e){return e[s]||[]},t.createDecorator=function(e){if(t.serviceRegistry.has(e))return t.serviceRegistry.get(e);const r=function(e,t,n){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");!function(e,t,r){t[i]===t?t[s].push({id:e,index:r}):(t[s]=[{id:e,index:r}],t[i]=t)}(r,e,n)};return r.toString=()=>e,t.serviceRegistry.set(e,r),r}},2585:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.IDecorationService=t.IUnicodeService=t.IOscLinkService=t.IOptionsService=t.ILogService=t.LogLevelEnum=t.IInstantiationService=t.ICharsetService=t.ICoreService=t.ICoreMouseService=t.IBufferService=void 0;const s=i(8343);var r;t.IBufferService=(0,s.createDecorator)("BufferService"),t.ICoreMouseService=(0,s.createDecorator)("CoreMouseService"),t.ICoreService=(0,s.createDecorator)("CoreService"),t.ICharsetService=(0,s.createDecorator)("CharsetService"),t.IInstantiationService=(0,s.createDecorator)("InstantiationService"),function(e){e[e.TRACE=0]="TRACE",e[e.DEBUG=1]="DEBUG",e[e.INFO=2]="INFO",e[e.WARN=3]="WARN",e[e.ERROR=4]="ERROR",e[e.OFF=5]="OFF"}(r||(t.LogLevelEnum=r={})),t.ILogService=(0,s.createDecorator)("LogService"),t.IOptionsService=(0,s.createDecorator)("OptionsService"),t.IOscLinkService=(0,s.createDecorator)("OscLinkService"),t.IUnicodeService=(0,s.createDecorator)("UnicodeService"),t.IDecorationService=(0,s.createDecorator)("DecorationService")},1480:(e,t,i)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeService=void 0;const s=i(8460),r=i(225);t.UnicodeService=class{constructor(){this._providers=Object.create(null),this._active="",this._onChange=new s.EventEmitter,this.onChange=this._onChange.event;const e=new r.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}dispose(){this._onChange.dispose()}get versions(){return Object.keys(this._providers)}get activeVersion(){return this._active}set activeVersion(e){if(!this._providers[e])throw new Error(`unknown Unicode version "${e}"`);this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)}register(e){this._providers[e.version]=e}wcwidth(e){return this._activeProvider.wcwidth(e)}getStringCellWidth(e){let t=0;const i=e.length;for(let s=0;s=i)return t+this.wcwidth(r);const n=e.charCodeAt(s);56320<=n&&n<=57343?r=1024*(r-55296)+n-56320+65536:t+=this.wcwidth(n)}t+=this.wcwidth(r)}return t}}}},t={};function i(s){var r=t[s];if(void 0!==r)return r.exports;var n=t[s]={exports:{}};return e[s].call(n.exports,n,n.exports,i),n.exports}var s={};return(()=>{var e=s;Object.defineProperty(e,"__esModule",{value:!0}),e.Terminal=void 0;const t=i(9042),r=i(3236),n=i(844),o=i(5741),a=i(8285),h=i(7975),c=i(7090),l=["cols","rows"];class d extends n.Disposable{constructor(e){super(),this._core=this.register(new r.Terminal(e)),this._addonManager=this.register(new o.AddonManager),this._publicOptions=Object.assign({},this._core.options);const t=e=>this._core.options[e],i=(e,t)=>{this._checkReadonlyOptions(e),this._core.options[e]=t};for(const e in this._core.options){const s={get:t.bind(this,e),set:i.bind(this,e)};Object.defineProperty(this._publicOptions,e,s)}}_checkReadonlyOptions(e){if(l.includes(e))throw new Error(`Option "${e}" can only be set in the constructor`)}_checkProposedApi(){if(!this._core.optionsService.rawOptions.allowProposedApi)throw new Error("You must set the allowProposedApi option to true to use proposed API")}get onBell(){return this._core.onBell}get onBinary(){return this._core.onBinary}get onCursorMove(){return this._core.onCursorMove}get onData(){return this._core.onData}get onKey(){return this._core.onKey}get onLineFeed(){return this._core.onLineFeed}get onRender(){return this._core.onRender}get onResize(){return this._core.onResize}get onScroll(){return this._core.onScroll}get onSelectionChange(){return this._core.onSelectionChange}get onTitleChange(){return this._core.onTitleChange}get onWriteParsed(){return this._core.onWriteParsed}get element(){return this._core.element}get parser(){return this._parser||(this._parser=new h.ParserApi(this._core)),this._parser}get unicode(){return this._checkProposedApi(),new c.UnicodeApi(this._core)}get textarea(){return this._core.textarea}get rows(){return this._core.rows}get cols(){return this._core.cols}get buffer(){return this._buffer||(this._buffer=this.register(new a.BufferNamespaceApi(this._core))),this._buffer}get markers(){return this._checkProposedApi(),this._core.markers}get modes(){const e=this._core.coreService.decPrivateModes;let t="none";switch(this._core.coreMouseService.activeProtocol){case"X10":t="x10";break;case"VT200":t="vt200";break;case"DRAG":t="drag";break;case"ANY":t="any"}return{applicationCursorKeysMode:e.applicationCursorKeys,applicationKeypadMode:e.applicationKeypad,bracketedPasteMode:e.bracketedPasteMode,insertMode:this._core.coreService.modes.insertMode,mouseTrackingMode:t,originMode:e.origin,reverseWraparoundMode:e.reverseWraparound,sendFocusMode:e.sendFocus,wraparoundMode:e.wraparound}}get options(){return this._publicOptions}set options(e){for(const t in e)this._publicOptions[t]=e[t]}blur(){this._core.blur()}focus(){this._core.focus()}resize(e,t){this._verifyIntegers(e,t),this._core.resize(e,t)}open(e){this._core.open(e)}attachCustomKeyEventHandler(e){this._core.attachCustomKeyEventHandler(e)}registerLinkProvider(e){return this._core.registerLinkProvider(e)}registerCharacterJoiner(e){return this._checkProposedApi(),this._core.registerCharacterJoiner(e)}deregisterCharacterJoiner(e){this._checkProposedApi(),this._core.deregisterCharacterJoiner(e)}registerMarker(e=0){return this._verifyIntegers(e),this._core.registerMarker(e)}registerDecoration(e){var t,i,s;return this._checkProposedApi(),this._verifyPositiveIntegers(null!==(t=e.x)&&void 0!==t?t:0,null!==(i=e.width)&&void 0!==i?i:0,null!==(s=e.height)&&void 0!==s?s:0),this._core.registerDecoration(e)}hasSelection(){return this._core.hasSelection()}select(e,t,i){this._verifyIntegers(e,t,i),this._core.select(e,t,i)}getSelection(){return this._core.getSelection()}getSelectionPosition(){return this._core.getSelectionPosition()}clearSelection(){this._core.clearSelection()}selectAll(){this._core.selectAll()}selectLines(e,t){this._verifyIntegers(e,t),this._core.selectLines(e,t)}dispose(){super.dispose()}scrollLines(e){this._verifyIntegers(e),this._core.scrollLines(e)}scrollPages(e){this._verifyIntegers(e),this._core.scrollPages(e)}scrollToTop(){this._core.scrollToTop()}scrollToBottom(){this._core.scrollToBottom()}scrollToLine(e){this._verifyIntegers(e),this._core.scrollToLine(e)}clear(){this._core.clear()}write(e,t){this._core.write(e,t)}writeln(e,t){this._core.write(e),this._core.write("\r\n",t)}paste(e){this._core.paste(e)}refresh(e,t){this._verifyIntegers(e,t),this._core.refresh(e,t)}reset(){this._core.reset()}clearTextureAtlas(){this._core.clearTextureAtlas()}loadAddon(e){this._addonManager.loadAddon(this,e)}static get strings(){return t}_verifyIntegers(...e){for(const t of e)if(t===1/0||isNaN(t)||t%1!=0)throw new Error("This API only accepts integers")}_verifyPositiveIntegers(...e){for(const t of e)if(t&&(t===1/0||isNaN(t)||t%1!=0||t<0))throw new Error("This API only accepts positive integers")}}e.Terminal=d})(),s})())); +//# sourceMappingURL=xterm.js.map \ No newline at end of file diff --git a/docs/CERTIFICATE_FIX_REPORT.md b/docs/CERTIFICATE_FIX_REPORT.md new file mode 100644 index 0000000..47500ab --- /dev/null +++ b/docs/CERTIFICATE_FIX_REPORT.md @@ -0,0 +1,254 @@ +# 证书修复实施与验收报告 + +日期:2026-09-23。工作区 `/Users/massif/TianshanOS`,分支 `main`,HEAD +`d6ed947a592265fa12754828bc79803fc50c1db2`。本报告描述该 HEAD 上的**未提交补丁**, +不是已部署版本;没有 commit、push、PR、真实 CA 操作、设备连接、刷写或重启。 + +开始时仅 `output/`、`tmp/` 是已有未跟踪目录,保留未动。仓库中没有找到额外 +AGENTS.md。已读取 README 构建说明及用户提供的完整修复方案。 +实际 SDK 为 ESP-IDF 5.5.2、目标 ESP32-S3,SDK 内 mbedTLS 为 **3.6.5**(不是方案引用的 +在线 3.6.1 文档版本);未升级 SDK、修改分区、调整权限或关闭 mTLS 验证。 + +## 交付状态 + +- 完成安装长度/边界、请求局部错误、缓存与快照互斥、UTC、元数据缓存、材料版本、 + 校时/材料通知、局部协调与有界重试、真实 TLS 运行态、待应用展示、自动注册适配。 +- 宿主测试通过;采用真实 SDK mbedTLS/cJSON,平台功能使用替身,业务代码用 ASan/UBSan。 +- ESP32-S3 固件和 WebUI 构建通过,实际命令及尺寸见后文。 +- **实机 Web 安装、TLS 握手、重启恢复与资源测量未执行。不能据此宣称生产可发布。** +- **用户已批准的范围补充:**修正通用服务管理器吞掉停止错误的问题。 + `stop_service_internal()` 失败时返回原错误、恢复原状态、不发送停止成功事件; + `ts_service_restart()` 也不会把运行中服务的停止失败当成可忽略的状态错误。 + `tests/certificate/test_service_stop.sh` 先从 HEAD 复现旧错误,再测试当前真实函数: + 一般失败、超时、状态错误均阻止重启;正常停止、重复停止与正常重启通过。 + 共享回调已静态核查:正常返回成功的流程不变;返回失败的服务不再被假标为已停止。 + 保留管理状态不代表能撤销其他模块内部的部分操作,其他服务实机故障未逐个注入。 + +## F1–F12 基线核对 + +所有问题在当前 HEAD 均仍存在,没有复用“已部署修复”的历史假设。 + +| 项目 | 基线核对 | 本轮处理 | +|---|---|---| +| F1 | 两个 Web 安装入口遗漏 NUL 长度 | 均改为实际内容长度 + 1 | +| F2 | 自动注册、CLI 已正确包含 NUL | 不再加一;全调用面核对 | +| F3 | 缺私钥与不匹配共用错误码 | `_ex` 请求局部错误;保留旧函数包装 | +| F4 | 页面忽略 error、PKI 翻译键错位 | 证书局部提取,键存在性回退,纯文本显示 | +| F5 | 浏览器校时没有通知 | 与 NTP 共用通知;失败不通知,丢事件可被兜底发现 | +| F6 | HTTPS 一次性 pending_init | 单一串行任务、两类事件、5 秒轻量检查 | +| F7 | 活动 HTTPS 复制材料 | 一致性拥有型快照;活动指纹与存储版本分开 | +| F8 | mktime、本地时区、未初始化 tm | 纯公历 UTC 算法;两个 HTTPS 时间消费者同步适配 | +| F9 | 读取缓存派生状态、刷新写 NVS | 静态元数据缓存;每次状态采样一次 now,派生状态不写 Flash | +| F10 | 32 字节序列号可溢出 serial[64] | serial[65]、有界编码、截断标志 | +| F11 | HTTPS 不是整套 WebUI | 验收端点仍为现有身份/权限 API | +| F12 | 通用 RUNNING 不代表实际监听 | cert.status 独立公开完整启动后的真实状态;停止失败正确传播,重启不继续 | + +本次没有在修复前建立完整的红灯测试基线;上述是源码证据,不冒充修复前实机复现。 +实施中故障测试曾发现“相同 PEM 幂等路径绕过损坏私钥检查”,已修复并保留回归用例。 + +## 文件与行为对应 + +| 文件 | 主要符号/用途 | 兼容边界 | +|---|---|---| +| `components/ts_cert/include/ts_cert.h` | 追加状态/validity/error、snapshot、generation | 原枚举 0..5 不变;原 esp_err_t 安装入口保留;新结构需全量重编译 | +| `components/ts_cert/src/ts_cert.c` | `install_material`、`info_from_crt`、`refresh_metadata`、`ts_cert_get_snapshot` | 原 NVS namespace/键不变;不把多键 set/erase 当事务 | +| `components/ts_cert/include/ts_cert_time.h`、`src/ts_cert_time.c` | `ts_cert_time_utc`、`ts_cert_time_days`、`ts_cert_hex` | 纯 C、无 TZ/全局时钟副作用;支持年份 1..9999 | +| `components/ts_api/src/ts_api_cert.c` | 两个 install、`add_validity`、`add_runtime` | 保留 code/error/data 协议、路径和权限;只增加字段 | +| `components/ts_core/ts_event/include/ts_event.h` | PKI 材料变更事件 | 小型 generation/kind 数据,不携带 PEM/指针 | +| `components/ts_net/src/ts_time_sync.c` | `notify_clock_updated`、UTC readiness | 继续使用原最小年份与原时间源策略,不声称时间经过认证 | +| `main/ts_services.c`、`main/ts_https_retry.h` | `https_coordinator`、串行启停、重试策略 | 不调用管理器重入自身;普通 GET/重复通知不重置预算 | +| `components/ts_core/ts_service/src/ts_service.c` | `stop_service_internal`、`ts_service_restart` | 用户批准的共享管理器最小修正;失败返回原错误,阻止假重启 | +| `components/ts_https/include/ts_https.h`、`src/ts_https.c` | runtime 快照、完整启动后发布、失败保留所有权 | 活动材料只在显式停止/重启后切换;非 mTLS 配置不强加 CA | +| `components/ts_https/src/ts_https_auth.c` | UTC 剩余天数 | 不改角色/权限策略 | +| `components/ts_pki_client/src/ts_pki_client.c` | 已有材料保留、安装返回值、协作取消 | 待校时/尚未生效不触发重新签发;缺 CA 不重新申请设备证书 | +| `components/ts_console/commands/ts_cmd_pki.c` | 新时间状态和容量提示 | 文件读取仍传 read_len+1;不再把所有无效状态写成 Expired | +| `components/ts_webui/web/js/app.js` | `certError`、`installCertMaterial`、`refreshCertStatus` | code===0 才成功;丢响应显示未确认,不自动重发 POST | +| `components/ts_webui/web/js/lang/{zh-CN,en-US}.js` | `pkiRepair` 文案 | 两种语言覆盖;缺新增字段的旧固件显示未知,不推断运行 | +| `components/{ts_cert,ts_api}/CMakeLists.txt` | 新源文件、API 私有 HTTPS 依赖 | ts_cert 不依赖 WebUI/API/main,无 SDK 变更 | +| `tests/certificate/` | 可运行宿主测试、临时夹具生成、生产函数提取 | 测试注入不进入生产 API | + +锁顺序为:材料锁内读写缓存/RNG/NVS与元数据 → 解锁 → 发布事件。HTTPS 获取自己的 +精确长度快照后才启动 TLS;不会持材料锁等待网络或服务管理器。CA 的小型 SD 副本写入 +仍串行处理,写入/关闭失败只是警告,不改变 NVS 保存成功结论。 + +NVS set/commit 或多键操作异常后进入 `storage_error`,旧 RAM 材料不被冒充为新保存结果, +阻止新的 TLS 加载;请重启后读回并检查实际存储。既有活动实例可继续运行,其版本与 +指纹仍来自自己的快照。这里没有断电跨键回滚保证,也不会自动清空 NVS。 + +长度契约仅适用于本轮 PEM 文本:已知跨度包含最后一个 NUL,跨度内无提前 NUL。 +两个安装容量均为 4000 字节含 NUL;4096 缓冲宏未改。JSON 解码后 cJSON 的 C 字符串 +不能保留原始 `\u0000` 后缀语义,本轮不声称 strlen 能检出该原始后缀。 + +## 调用者审查 + +| 调用来源 | 缓冲/长度 | 结论 | +|---|---|---| +| Web `api_cert_install` / `api_cert_install_ca` | cJSON 拥有的终止字符串;strlen+1 | 修正长度;底层再次检查边界 | +| CLI `cmd_pki_install` | malloc(file_size+1),fread 后补 NUL;read_len+1 | 保持正确长度;文件内容上限 3999 | +| 自动批准 `ts_pki_client_submit_csr` | cJSON 字符串;strlen+1 | 长度原本正确;新增设备证书/CA 结果检查 | +| 下载 `ts_pki_client_install_certificate` | cJSON 字符串;strlen+1 | CA 失败或缺失不能报全流程完成 | +| 配置包签名者 `ts_config_pack` | PEM 文本;strlen+1 | 无需更改;没有改变配置包授权或用途规则 | +| `ts_cert_get_info` | 以前重复解析缓存;现在读取元数据 | 不暴露材料指针,不重复解析 | +| HTTPS `load_certificates` | 一次一致性快照,精确大小副本 | 替代三次独立读取;活动指纹取叶证书 DER SHA-256 | + +搜索未发现 `ts_cert_info_t` 作为未经版本化二进制结构写入持久化存储。 + +## 实际执行证据 + +宿主命令:`./tests/certificate/run_host.sh`,退出码 0。结果: + +```text +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged +``` + +Node `--check` 验证 app.js 与两种语言资源;`git diff --check` 验证补丁空白。 +宿主测试使用 Command Line Tools 的 clang,应用代码开启 ASan/UBSan;SDK mbedTLS +宿主库没有 sanitizer 插桩,也未使用 ESP32 的硬件加速配置。 + +目标构建: + +```sh +. /Users/massif/esp/v5.5.2/esp-idf/export.sh +export IDF_PYTHON_ENV_PATH=/Users/massif/.espressif/python_env/idf5.5_py3.12_env +export PATH="$IDF_PYTHON_ENV_PATH/bin:$PATH" +./tools/build.sh +``` + +使用已有 Python 3.12 构建配置。最初 export 选择 3.14,与现有 CMake 配置不符;随后 +改为命令局部的 3.12 环境。沙箱禁止 psutil 的 sysctl 进程读取,批准放开本地构建后继续。 +没有 fullclean、重配目标、改变全局 PATH、修改 Xcode 许可或绕过 SDK 安全配置。 + +第一次编译发现 `_Atomic TaskHandle_t*` 不能传给 FreeRTOS 的普通输出参数,改为普通 +句柄与原子运行/取消标记;后续目标编译通过。宿主曾发现相同 PEM 的私钥检查回归并修复。 +这些失败不被隐藏为“第一次就全绿”。最终构建退出码 0,版本 `0.5.1+d6ed947d.09232301`(未提交源码的本地构建)。 +Node v24.10.0,Apple clang 21.0.0。优化后的 app.js 通过语法检查,gzip 解压内容与 +优化文件一致。应用分区 3,145,728 字节,剩余 988000 字节(约 31%)。 + +| 产物 | 原有构建产物字节 | 本轮字节 | 差值 | SHA-256 | +|---|---:|---:|---:|---| +| TianShanOS.bin | 2154096 | 2157728 | +3632 | `7f80532700f622abc7b46cbf2e7f314e35b0332a5aa3204fe6195404613ff0e5` | +| www.bin | 3145728 | 3145728 | +0 | `6ce320ce1f67ae4b35970dde8b74ce6e0f40c9e4e6b74d2c9056ca47ba4d3adc` | + +此比较针对工作区原有二进制,未另建干净基线固件,因此差值不是独立性能测量。 +本轮二进制和日志保留在 `/tmp/tianshan-certificate-tests/artifacts/`;仓库中原本受跟踪的 +两个 build/*.bin 恢复为修改前内容,避免将生成文件混入源码补丁。它们不能被当作本轮 +新固件使用;重新构建或使用上述临时验证产物,部署前仍须完成实机验收。 + +## 62 项验收映射 + +`HOST` 表示该行核心行为已在宿主执行;`PARTIAL` 表示仅覆盖其中明确列出的部分, +仍缺整项验收;`NOT_RUN` 表示未执行。即便 HOST,也不等于真实 ESP32/WebUI/TLS 验收。 + +| 编号 | 状态 | 实际测试 / 限制 | +|---|---|---| +| A01 | PARTIAL | `test_api` 正常设备 PEM、NVS/缓存;`test_material` 模拟重载;真实 Web/Flash 重启未测 | +| A02 | PARTIAL | `test_material` 拼接双证书 CA,真实 mbedTLS;真实 Web 未测 | +| A03 | PARTIAL | LF/CRLF/无末尾换行已跑;前端 trim;全部空白排列未穷举 | +| A04 | HOST | `test_api` 缺失/数字/空串;`test_material` 空白 | +| A05 | HOST | `test_material` 坏 PEM,原材料/版本不变 | +| A06 | HOST | `test_material` 合法 CA + 损坏 CA,全批拒绝 | +| A07 | HOST | `test_material` 缺私钥与模块未初始化区分 | +| A08 | HOST | `test_material` 另一 P-256 公钥拒绝,原材料不变 | +| A09 | HOST | `test_material` 损坏已存私钥;同 PEM 不绕过检查 | +| A10 | HOST | `test_material` 漏 NUL/提前 NUL/超长;ASan/UBSan | +| A11 | PARTIAL | 测 3999..4096 每个长度的边界/解析分流;未生成恰好 3999 字节有效证书验证真实 NVS 容量 | +| A12 | PARTIAL | 缓存分配失败与 mbedTLS 分配错误返回注入;不是穷举库内全部分配点 | +| A13 | HOST | 模拟 set/commit 失败;commit 失败后 mock 存储可已变化,缓存和成功事件不伪更新 | +| A14 | PARTIAL | 宿主无 SD 的路径正常安装;未模拟 SD 部分写及 close 失败 | +| A15 | HOST | 相同 PEM 的写入计数与版本不增 | +| A16 | HOST | `test_ui` POST 超时只提交一次,结果未确认;后端可能已写入的语义保留 | +| A17 | PARTIAL | 安装返回值路径已静态核对;未运行真实自动批准/下载服务器 | +| A18 | PARTIAL | `test_material` init 读取/分配失败与坏私钥;真实 NVS 损坏恢复未测 | +| B01 | HOST | UTC/CST-8/PST8PDT 同 epoch 结果一致 | +| B02 | PARTIAL | 算法不调用 TZ/mktime;PST8PDT 复核;未逐个枚举 DST 跳变 epoch | +| B03 | HOST | 2000/2024 闰日有效、2100 闰日无效 | +| B04 | PARTIAL | not_before-1 与端点已跑;+1 尚未独立列测 | +| B05 | PARTIAL | not_after 与 +1 已跑;-1 尚未独立列测 | +| B06 | HOST | 86399/0/-1/-86400/-86401 与 UI 不足一天 | +| B07 | HOST | 2050、9999 年 64 位结果 | +| B08 | HOST | 1970、time()=-1、阈值前时间未就绪 | +| B09 | HOST | `test_time_cancel` 阈值 UTC 前后一秒、三种 TZ | +| B10 | PARTIAL | 无证书、坏 PEM/私钥;纯 UTC 非法日期;未构造签名证书起止倒置夹具 | +| B11 | HOST | 解码后长度 0/1/20/31/32/33;终止、截断、保护字节与 sanitizer | +| B12 | HOST | 状态读取 1000 次 NVS set/commit 计数不变,再跨时间边界 | +| B13 | HOST | 实际生成 CSR 后读取 100 次保持 CSR_PENDING,无状态持久化 | +| B14 | PARTIAL | 自动注册的存在性条件与回调语义静态审查;未运行真实自动注册任务闭环 | +| C01 | PARTIAL | `test_coordinator` 单任务、单实例;实机启动顺序未测 | +| C02 | PARTIAL | 真实校时通知/材料前提分别测;协调器假前提→真前提;未实机组合 | +| C03 | PARTIAL | 同 C02;后安装材料的真实设备闭环未测 | +| C04 | PARTIAL | 底层 CA 安装不依赖私钥,条件统一;各种真实顺序未实机穷举 | +| C05 | HOST | 重复通知保留等待资格;创建任务/订阅计数不增 | +| C06 | HOST | 100 次重复通知/启动不重复 URI/实例 | +| C07 | HOST | init、默认端点、URI/TLS 启动故障;1/5/15 秒虚拟重试 | +| C08 | HOST | 四次失败后普通重复事件/时间推进不再重试 | +| C09 | HOST | 明确 stop/start 恢复;纯策略新 generation 重置预算 | +| C10 | HOST | 停止后大量旧通知与旧到期时间不能启动 | +| C11 | HOST | 模拟 TLS start 正在进行,另一线程 stop、材料变更;stop 返回后保持停止 | +| C12 | PARTIAL | 通知丢失不回滚保存;协调器无事件也检查前提;不是实机队列压力测试 | +| C13 | PARTIAL | not_before 派生与兜底分别测;真实无事件等待到日期未实机测 | +| C14 | PARTIAL | 活动 A/存储 B 的 API 版本与指纹分离;真实握手仍 A 未测 | +| C15 | PARTIAL | CA generation 更新和状态重读;真实 CA-only 握手变化未测 | +| C16 | PARTIAL | 模拟 stop/deinit/init 重新加载 generation;真实重启和 B 握手未测 | +| C17 | PARTIAL | 生成新密钥/删除凭证后已有快照仍自洽;真实会话未测 | +| C18 | PARTIAL | pthread 安装与状态/快照并发;不是所有 ESP 任务与 NVS/校时交错的穷举 | +| C19 | HOST | 快照取 B 后安装 A,持有的 B 副本和旧 generation 不变 | +| C20 | PARTIAL | TLS/协调器停止失败与半启动清理保留句柄;管理器停止/重启真实函数错误传播已测;设备用户入口未测 | +| C21 | PARTIAL | 真实取消函数等待超时不强删;材料锁并发测试;完整 HTTP 注册取消竞态未实机测 | +| C22 | HOST | `test_lifecycle` 非 mTLS 缺 CA 能启动;没有自动降级 | +| D01 | HOST | message/error/空白/布尔 true 类型选择 | +| D02 | HOST | 中英文实际资源与缺键回退;相邻 PKI 提示检查 | +| D03 | HOST | POST 成功/失败/超时/刷新抛异常均恢复按钮,刷新不改已保存结果 | +| D04 | PARTIAL | 旧字段缺失的有效期/HTTPS 显示未知;未与旧固件做真实浏览器组合 | +| D05 | HOST | HTML 字符串使用 textContent,不拼入 HTML;DOM 替身测试 | +| D06 | NOT_RUN | 没有真实 mTLS 设备/客户端,不能认定认证通过 | +| D07 | PARTIAL | 未修改角色/用途/权限策略;旧真实凭证/配置包端到端回归未跑 | +| D08 | PARTIAL | 测试凭证临时生成、不打印密钥;源码/产物变更审查;不是全站日志安全审计 | + +## 资源与升级 + +- 新增一个 8192 字节内部 RAM 栈的协调任务、一个静态材料 mutex、两个保留订阅与少量元数据。 + 这是配置申请量,不是实机测量的最终总消耗;TCB、分配器开销、库临时内存另计。 +- 材料副本按实际长度优先 PSRAM,失败回退内部堆;错误检查后再交换。没有把 4KB/4KB + PEM 固定数组放入事件栈。事件处理器只唤醒协调任务,不解析/TLS 启动。 +- 当前材料的叶证书元数据、匹配结果、CA 解析结果和指纹被缓存。安装复用候选解析对象; + GET 与 5 秒无变化兜底不重新解析、不写 NVS、不创建新 TLS 实例。 +- 第一次瞬态失败后至多再试 3 次(1、5、15 秒)。缺前提不做快速重试;版本变化、 + 明确重新启动、前提由假变真才重置预算。用户停止优先。 +- 内部空闲堆/PSRAM、协调任务栈 high-water、失败前后资源趋势:**未实机测量**。 +- 保留旧 NVS。固件与 WebUI 应成套更新;只升级一侧不算完整交付。新 UI 对旧固件新增 + 字段缺失显示待确认;旧 UI 无法正确表达新状态,升级说明须提醒同时更新页面。 +- 运行中更新证书或 CA 不自动断连接。重启设备或成功的显式服务重启后才尝试加载新材料。 + 缺时间/CA、密钥不匹配、证书未生效/过期时 HTTP 管理路径保留,HTTPS 不新启动。 +- 构建产物属于本地验证附件,不包含在本补丁中;没有改动用户原有 output/tmp 内容。 + +## 实机放行步骤(尚未执行) + +1. 在明确授权的 ESP32-S3 测试设备记录旧版本、现有凭证及可恢复方案,不清空生产 NVS。 +2. 更新固件与 WebUI。设备生成专用测试密钥/CSR,用隔离测试 CA 签发;不得拿本报告 + 宿主生成的私钥替代设备 CSR 主流程。 +3. 交叉执行先校时/后装、先装/后校时、CA/设备证书互换顺序;断开 NTP 后用安全页 + 的浏览器校时按钮,验证失败能重试及设备时间/来源如实显示。 +4. 从正常页面安装有效/损坏/不匹配/过期/未来证书,记录脱敏响应、保存内容与真实状态。 +5. 正确信任 CA、SAN 地址、客户端证书/私钥下,验证现有 `/api/auth/whoami`: + + ```sh + curl --fail-with-body --cacert ./test-server-trust.pem \ + --cert ./test-admin-cert.pem --key ./test-admin-key.pem \ + "https://${TEST_DEVICE_HOST}:${TEST_HTTPS_PORT}/api/auth/whoami" + ``` + + 不使用 `-k/--insecure`。分别验证无客户端证书、非信任客户端证书被拒绝及现有角色权限。 +6. 握手确认活动 A 的叶 DER SHA-256;存储 B 后握手仍 A、页面常驻待应用;重启后 + 完整认证握手确认 B。只换 CA 时也核对 configured/loaded 版本及客户端信任变化。 +7. 测试停止与重启、重试期间停止、删除/换钥期间活动会话;停止失败须从真正用户入口 + 保留错误,不能只测底层函数。管理器宿主回归已通过,仍需设备入口验证。 +8. 记录内部堆/PSRAM、任务栈余量、重复故障后的趋势和实际镜像版本。所有未测项继续 + 标为未验证,不能因页面显示有效或编译通过而取消。 diff --git a/docs/OS_RUNTIME_AUDIT_2026-09-23.md b/docs/OS_RUNTIME_AUDIT_2026-09-23.md new file mode 100644 index 0000000..c1dc785 --- /dev/null +++ b/docs/OS_RUNTIME_AUDIT_2026-09-23.md @@ -0,0 +1,145 @@ +# 旧版 0.5.1 串口与模型管理链路核查 + +日期:2026-09-23。结论:卡片消失是确定的软件问题;模型自动启动链条在本段日志中走通,但状态可信度、编辑安全性、SSH 开销与身份验证仍有独立缺陷。本次只分析,未修改产品代码、连接设备、执行远程命令或刷写固件。此前证书修复保留。 + +## 证据边界 + +- 输入:`/Users/massif/Downloads/serial.raw.log`,283358 字节、3932 行;以及《卡片消失原因与最佳修复方案.md》。附件中的修复建议作为待核实观点,不作为本次自动改代码授权。 +- 用户确认日志来自修改前的 0.5.1。日志没有完整启动头和镜像 SHA,不能仅凭版本号证明它与当前 HEAD 完全相同。 +- 源码基线:`d6ed947a592265fa12754828bc79803fc50c1db2`,叠加此前未提交证书补丁。下述规则引擎、自动化 API/动作管理器、SSH 客户端/日志监控、日志系统均与 HEAD 无差异;前端所引卡片与规则编辑代码不属于证书补丁。 +- 日志约覆盖启动后 37 秒至 1283 秒,中间有长空白;不是连续、完整开机验收。未出现明确 W/E 级记录、panic、看门狗复位或分配失败记录;这不等于整个系统没有故障。 +- 日志有截断、拼接和重复行。下述“120 次”等是文本记录计数,不保证一条日志严格对应一个唯一操作;不能据重复日志直接断定模型重复启动。 + +## 实机日志实际说明了什么 + +| 行号 | 观察 | 能得出的结论 | +|---|---|---| +| 1–3 | LPMU boot successful,ON | 固件把电源/启动状态置为 ON,不等于远端 OS 或模型 API 已就绪 | +| 9–10 | 浏览器校时成功 | 当时设备需要较大幅度校时;没有 NTP/HTTPS 启动全链路证据 | +| 200–213 | 规则数先变 6,再变 7;删除 Qwen 规则文件,随后触发并注册 | 保存操作确实经过删除/重建;首次保存附近出现自动触发,但不能单凭此证明重复启动 | +| 241、2299–2301 | 主模型 checking → ready,随后触发 Embedding | 日志模式检测约 287.7 秒后成功,自动链路推进 | +| 2338、2960–2962 | Embedding checking → ready,随后触发 Reranker | 约 87.2 秒后推进 | +| 2997、3683–3684 | Reranker checking → ready,监控任务退出 | 约 97.0 秒后检测成功 | +| 3686–3706、3832–3838 | 再次多轮 6 → 7、删除与注册 | 编辑仍持续使用删除/重建;卡片不显示不能解释为规则永久丢失 | + +三个 ready 都来自远程日志出现 `Application startup complete`。没有真实推理请求、端口健康测试或启动后持续存活证据,因此不能把它们表述为“模型一直正常服务”。 + +## 发现及决策 + +### R1 / P1:卡片显示与启动方式混用;保留条件还必须补后端判断 + +**已确认。** `components/ts_webui/web/js/app.js:4341` 使用 `r.enabled && r.manual_trigger` 筛选卡片。切换自动模式时字段变 false,卡片被过滤,日志和停止入口一起消失。 + +`app.js:22027` 附近提交逻辑只在非手动模式收集条件;手动保存把条件数组写成空。附件关于“条件会丢失”的判断正确。 + +**附件遗漏:**`components/ts_automation/src/ts_rule_engine.c:686` 的 `ts_rule_evaluate()` 只检查 enabled、冷却时间与条件,不检查 manual_trigger;`:657` 通过空条件返回 false 间接避免手动规则自动执行。仅在 UI 中保留条件,会使手动规则重新参与自动判断。 + +修复应把卡片可见性与启动方式分开,后端明确跳过仅手动规则,再允许保留自动条件。已有手动卡片、服务型模型规则可作为旧配置的默认显示集合;缺省与明确 false 必须区分,避免用户隐藏后又被重新显示。字段须贯通列表/详情 API、NVS、SD JSON 和配置包导入导出。已被旧版本清空的条件无法凭空恢复,必须提示补配。 + +### R2 / P1:保存规则可能丢配置、重置运行历史,还可能假报成功 + +**日志与源码确认删除/重建;异常损失属于代码风险,日志未发生。** `app.js:22106` 附近先调用 delete,再 add,且没有检查 delete 的业务 code。网络中断或新规则校验/分配失败发生在两步之间,会留下已删除状态。新建规则在 `ts_rule_engine.c:430` 附近 memset,重置触发时间/次数;冷却状态变化可能改变再次触发行为。 + +后端 `ts_rule_register():353` 已有同 ID 原位更新分支,**但不能直接认为它安全**:先释放旧数组,再分配新数组;分配失败仍可返回成功。新增分支也没有完整处理分配失败。`ts_rules_save():2323` 先清空旧 NVS,单条序列化/写入失败可能只打印警告;上层注册/删除不传播保存错误。SD 文件以 `fopen("w")` 直接覆盖,导出结果也没有完整传回。因此“保存成功”不保证重启后能恢复。 + +修复:准备并验证完整新配置后再替换,避免先删;保留适合保留的运行统计,定义修改条件/动作时何时重新评估;持久化错误返回给用户。不能宣称 NVS 与 SD 多次写入是一个原子事务。对旧配置包优先级也要保留:启动加载优先 SD,且同名 `.tscfg` 优先于 `.json`,不能只更新 JSON 后声称一定生效。 + +### R3 / P1:运行中编辑规则存在释放后使用风险 + +**源码确认危险交错,未在该实机日志观察到崩溃。** `ts_rule_engine.c:686` 的 evaluate 在取得规则指针后解锁,再读取条件和动作、执行网络操作;手动 trigger(`:808` 附近)也把内部动作指针带到锁外。与此同时 unregister(`:481`)可释放数组并移动规则,register 可释放并替换数组。`ts_rule_get():568` 同样返回解锁后的内部指针。 + +可能结果是偶发崩溃、执行错误动作或把统计写到另一条规则;“改为原位更新”本身不能消除这个问题。 + +修复:在短锁内取得本次执行所需的有界快照或明确的对象使用权,锁外执行网络操作,结束时按稳定 ID/版本回写。不要持全局规则锁等 SSH。对 ESP32 要限制快照尺寸和并发执行数量,而不是复制整个规则库。 + +### R4 / P1:状态未知被当成未运行;ready 也不是持续健康状态 + +**源码确认;本日志没有模型后续退出的证据。** `app.js:4370–4446` 的进程检查在熔断、SSH 错误等情况下把 isRunning 置为 false,再显示“未运行”并允许触发。API 业务失败也未先验证 code。可能只是暂时查不到,却误导用户再次启动。 + +`ts_ssh_log_watch.c:263–268` 一旦找到就绪字符串就写 ready 并退出;UI 后续 3 秒轮询(`app.js:4490` 附近)主要读取该变量,不是持续远程健康探测。卡片的进程检查也不是每 3 秒重新执行。因此页面可能保留历史 ready。自动规则链依赖该变量时也有相同语义问题。 + +另外 `ts_action_manager.c:1434` 启动日志监控失败只写警告,没有同步变成可靠的失败状态;命令发出成功不能代表模型启动成功。 + +修复:至少分清“启动中、已就绪、已停止、检查失败/状态未知”,带观测时间;未知时不能据此放行重复启动。后端也要提供重复启动保护,不能只靠按钮禁用。就绪后的低频健康检查应按主机合并、有界执行,避免每张卡片各自高频 SSH。 + +### R5 / P2:每次查日志都重新认证,ESP32 做了大量重复工作 + +**日志与源码吻合。** 文本中有 120 条 SSH 连接/认证完成记录、100 条 Checking log、101 条结果记录;绝大多数日志属于 SSH 与密码学细节。`ts_ssh_log_watch.c:98–219` 每轮加载私钥、建会话、连接认证、执行 grep、断开并释放。 + +配置是完成一次检查后等 3000 ms,实际正常连续轮次大约相隔 4.75 秒。120 对 signv 开始/结束日志的耗时中位数约 722 ms,范围 711–1175 ms。**这是日志测出的墙钟时间,不能换算成 CPU 使用率。**检查本身大约 1.7 秒,也包含网络/调度等耗时。 + +修复优先级:先减少握手次数与 INFO 调试日志;复用受限数量的主机连接或一次远程等待/合并检查,并设置真正的截止时间与取消。避免为每个模型建立永久独立连接。监控任务当前每个申请 8 KiB 栈,多模型扩展前须测内部堆、栈余量、并发上限。 + +### R6 / P1:自动化 SSH 没有和网页操作保持相同的远端身份检查 + +**源码确认,不代表此次发生攻击。** `ts_api_ssh.c:321–335` 在 connect 后验证 known_hosts;但 `ts_action_manager.c:1329–1345` 和 `ts_ssh_log_watch.c:185–195` 连接后直接执行命令,没有对应验证。SSH 客户端 `ts_ssh_client.c:293–316` 本身也没有提供主机信任检查。 + +日志中网页路径有 Host key verified,而自动模型启动/日志轮询路径没有;这与代码一致,不能把网页曾验证过等同于后续连接都已验证。 + +网页验证位置也晚于用户认证,因为 connect 实际包含认证。密码模式下,不能等凭据已经发出后再拒绝错误主机。 + +修复:将连接分为握手、主机信任校验、用户认证;所有自动/手动路径统一遵守。自动任务遇到未知或变更指纹应停止并报告,沿用现有人工信任流程,不自动接受新指纹。 + +### R7 / P2:日志本身存在截断与并发串行化问题,且打印密钥文本前缀 + +**日志确认格式损坏;具体每条损坏来源不能仅凭记录唯一归因。** 207、210、241、2997 行等长命令被截断/拼接;211、246 等处有重复行。 + +`ts_log.c:1000–1038` 用共享 static 512 字节缓冲和共享 in_hook;格式化无互斥,输出前已清除 in_hook。并发线程可覆盖尚未输出的内容;长行会截断。当前 SDK log v1 直接调用 hook,没有替这个缓冲加锁(已核查本机 SDK 源码)。当前配置启用该 hook,环形日志仅 500 条,密集调试内容也会挤掉历史线索。 + +`ts_ssh_client.c:424` INFO 打印私钥文本前 50 字符,日志有 120 条;并非完整私钥,也不能据此断定私钥已可被还原,但不应保留这种输出。去掉密钥文本、降低密码学内部调试级别;日志改为有界且线程安全的格式化/输出,明确截断,不长时间持有临界区。 + +时间戳在不同 tag 之间偶有约 1 秒回退;自建 TS_LOG 使用 esp_timer、ESP_LOG 使用 SDK 时间源,不能将这种差值直接认定为设备时钟故障。 + +### R8 / P1:日志监控替换/取消的生命周期不安全 + +**源码风险,当前日志没有重复监控替换或强删任务证据。** `ts_ssh_log_watch.c:293–313` 任务退出会自行 free(task);`:331–345` 替换同名任务时,调用方解锁后轮询 existing->is_running,旧任务可能已释放它。stop/stop_all(`:407`、`:468`)有类似问题,还会强制删除可能正在 SSH 操作中的任务,绕过 socket、会话和私钥缓冲清理。后两 API 未检出外部 C 调用者,不能说当前常规操作必经强删。 + +修复:明确谁持有对象、谁负责释放,以完成通知确认退出;网络调用可取消、等待有界,避免依赖已释放对象的标志。重复启动新监控前确认旧监控已退出或用代次隔离,防止旧任务覆盖新状态。 + +### R9 / P2:配置了超时,不代表 SSH 各阶段都能按时退出 + +**源码风险,日志里没有连接卡死。** `ts_ssh_client.c:293` 的握手 EAGAIN 循环、`:316` 的密码认证循环反复 wait_socket,没有总截止时间;已有 SO_RCVTIMEO/SO_SNDTIMEO 不能替代整个重试循环的截止时间。日志监控自己的 600/800 秒超时只在每轮调用前检查,若卡在连接里,外层无法及时终止。 + +修复:连接/握手/认证/执行共享单调时钟截止时间,等待时检查取消;不要仅增加外围定时器或到期强删任务。 + +### R10 / P2:日志匹配字符串并未真正转义 + +**静态确认,本次字符串不含危险字符,未触发。** `ts_ssh_log_watch.c:130–158` 虽称转义,实际只是 strncpy,然后把 pattern 与路径放进 shell 单引号。包含单引号时可破坏命令,导致检测错误甚至改变执行含义;snprintf 截断也未完整检查。 + +修复:统一 shell 参数编码并校验长度,固定字符串 grep 使用明确选项边界。不是要求禁止用户使用正常的包含引号的日志文本。 + +## 对附件“最佳方案”的结论 + +方向正确,但不足以直接作为完整实施纲要。批准实施前应补齐: + +1. 可见性独立;规则禁用不应让仍运行模型的管理入口一起消失,需明确产品语义。 +2. 保留条件的同时,后端真正执行仅手动语义;旧版丢失条件要提示恢复。 +3. 以安全更新代替删除重建;先解决分配失败、持久化错误和运行中对象生命周期,不能只换 API 调用。 +4. “不重复启动”由后端保证;未知状态不能当成停止;定义用户主动停止后是否允许自动规则再拉起。当前字段不足以表达维护暂停,此项需要产品决策,不能私自选择。 +5. 不把模型 ready 文本匹配当作长期健康;后续探测要有频率/并发预算。 + +推荐分包:第一包修模型卡片、模式切换、规则安全更新与状态真假;第二包统一 SSH 信任、生命周期、超时并降低轮询成本;日志可观测性修复可与第二包同步。都不需要重做全局 OS 架构。 + +## 本次验证与未验证 + +- 完整扫描 3932 行,按 tag、级别、状态变化和连接/签名配对汇总;清洗副本 `/tmp/tianshan-serial-clean.log`。 +- 从当前 app.js 提取真实过滤表达式和 submitAddRule 函数,在 Node VM 中使用模拟 DOM/API 执行。复现:自动卡片被过滤、手动保存清空条件、delete 业务失败仍继续 add。脚本 `/tmp/tianshan-card-audit.cjs`,退出码 0。这不是浏览器真机操作。 +- 校对关键模块与 HEAD 无差异,并核对本机 SDK log v1 调用路径。 +- 并发释放、内存不足、存储失败、恶意主机、网络黑洞等为静态确认的缺陷路径,未宣称已在真机注入复现。 +- 未运行模型推理、压力测试、浏览器自动化、硬件资源测量;未修改产品代码。 + +## 与此前证书修复的关系 + +这份日志只能证明浏览器校时成功,不能验证新补丁的证书安装、HTTPS 启动、活动证书切换;也没有充分证据判定当时 NTP/HTTPS 的最终状态。旧日志不能用于宣称新固件回归失败或成功。 + +此前证书修复不覆盖上述模型规则/SSH 日志监控/日志 hook 缺陷。PKI 自动注册任务的取消修复也不等于 SSH 日志监控取消已安全。这些应独立验收。 + +## 建议实机补测 + +- 按自动→手动→保存→自动操作:卡片存在、条件不丢、手动期间条件为真也不自动启动。 +- 模型正在启动/运行时修改规则:不崩溃、不串规则、不重复拉起;保存故障后旧规则可用且界面报错。 +- SSH 暂时断开:界面显示未知而非停止;恢复后状态收敛;连接黑洞能按截止时间退出。 +- 模型 ready 后杀进程:状态及时失效;用户主动停止后的自动恢复策略符合产品选择。 +- 替换 SSH 主机指纹:所有自动与手动路径均拒绝,不能先执行命令再验证。 +- 多模型连续启动/取消:监控任务、连接、内部堆和栈余量无持续恶化;日志无密钥文本及串行损坏。 +- 使用新证书固件另跑证书报告中的硬件验收,记录镜像 SHA,避免只用 0.5.1 版本号区分镜像。 diff --git a/docs/PROMPT_REPAIR_REPORT.md b/docs/PROMPT_REPAIR_REPORT.md new file mode 100644 index 0000000..99b0c95 --- /dev/null +++ b/docs/PROMPT_REPAIR_REPORT.md @@ -0,0 +1,34 @@ +# 用户提示与操作结果修复记录 + +本次包含历史 N01—N14 提示语核查及两轮审查确认的 R1—R6。代码已修复,本地主机和浏览器回归通过;未执行真实设备验收。 + +## 最终行为 + +- 实际内联翻译入口等待语言就绪,处理加载失败、超时、重试和快速切换;补齐中英文键与参数,内部枚举转换为用户可读状态。用户输入、文件名、路径、命令和远端输出不强制翻译。 +- REST 业务失败保持既有返回契约,具体写操作显式校验结果。HTTP 错误保留 error/message,超时覆盖响应体读取;未确认的写入不当作成功,也不自动重发。 +- 退出接口单独遵守 success:true 契约;其他接口不因此放宽。区分本地退出与服务端响应,旧退出回执不清除新的登录。 +- SSH 完成事件、匹配成功/失败、超时、取消、冲突与未知状态分别处理;会话已受理不等于后台进程就绪。保持原匹配规则。 +- 终端恢复等待实际确认;资源加载失败可重试,销毁实例不能迟到重连。LPMU 可达、不可达与检测未知分开,不自动重放电源脉冲。 +- 上传、下载、删除及配置应用保留逐项/部分失败结果。下载只称已发起;上传不等于验证通过,验证通过不等于已应用。 +- Toast 取消旧计时器,动态文本安全输出;有效新尝试可替换旧失败,迟到成功或失败不能覆盖新尝试。 + +## 两轮审查补修 + +|问题|修改|回归| +|---|---|---| +|R1 接口真实契约不一致|HTTP 错误先处理;退出、登录按自身契约;退出与新登录归属|401 error、成功退出、异常退出、其他接口拒绝宽松成功、迟到退出| +|R2 重复初始化与旧页面更新|首次启动/每次导航分离;主要页面读取校验导航有效性;只取消自己的订阅|已登录冷启动、旧页面迟到、失败重试、外部订阅保留、旧 finally 不释放新锁| +|R3 旧验证应用入口|绑定文件/路径/上传代次;重新上传立即失效;重叠写入不声称已确认最终文件|验证交替、旧成功晚到、已打开确认失效、同路径重叠上传| +|R4 新成功被旧错误遮住|有效尝试决定当前提示;不按响应到达顺序更新|快速重试、旧成功/旧失败分别晚到| +|R5 旧操作关闭新弹窗|成功、错误、finally 校验实例;任务记录独立于弹窗|A/B 弹窗交错、新按钮状态、关闭后结果保留| +|R6 上传后列表不刷新|固定目的目录;上传结果与刷新结果分开;目录请求代次校验|跨目录上传、同/跨目录刷新乱序、刷新失败不改上传成功统计| + +## 验证 + +- `npm ci --prefix tests/prompts`:锁定 Acorn / Playwright 依赖。 +- `npm test --prefix tests/prompts`:静态与实际生产函数 VM 测试 38/38 通过。 +- `npm run test:browser --prefix tests/prompts`:实际网页入口 Chrome 测试 36/36 通过,API/WebSocket 模拟,外部请求拦截。 +- 新增 25 项浏览器回归在修复前源码快照上全部失败、当前源码全部通过。历史快照和本地原始日志属于工作记录,不作为发布附件。 +- 既有证书与运行时 UI 回归通过。固件版本与整体构建结果见 `releases/v0.5.2-validation.md`。 + +VM 测试不等于浏览器渲染,浏览器模拟不等于真实设备。实际会话吊销、文件覆盖与配置生效、SSH 终态、断网恢复、保护策略、下载落盘及旧版本升级仍需设备/部署环境验收。任务记录仅保留在当前网页会话,不承诺刷新浏览器后的历史持久化。 diff --git a/docs/releases/v0.5.2-validation.md b/docs/releases/v0.5.2-validation.md new file mode 100644 index 0000000..bf76de9 --- /dev/null +++ b/docs/releases/v0.5.2-validation.md @@ -0,0 +1,51 @@ +# v0.5.2 提交与发布验证 + +基于上游 `d6ed947a592265fa12754828bc79803fc50c1db2`,合并证书/HTTPS、自动化/SSH/日志与 WebUI 提示修复。保留原有设备策略、分区和权限;没有设备连接、刷机、重启或模型启动/停止。 + +## 提交前验证 + +- `./tests/runtime/run_all.sh`:生产 codec/store/engine/SSH/service/watcher/log 等主机回归通过;含持久化故障注入、取消/代次/实例身份与实际 UI 函数。C 使用 ASan/UBSan。 +- `./tests/certificate/run_host.sh`:真实 SDK mbedTLS/cJSON 与平台替身测试通过;覆盖材料、时间、HTTPS 生命周期、协调、API 及服务停止失败。 +- `./tests/certificate/test_service_stop.sh`:原缺陷固定基线为 d6ed947;不再以变化的 HEAD 当旧代码,提交后仍能执行。 +- `npm test --prefix tests/prompts`:38/38;`npm run test:browser --prefix tests/prompts`:36/36。 +- `python3 tests/release/test_release.py`:3 项通过,覆盖实际发布条件矩阵、版本不一致、缺失/非中文说明的拒绝,以及提交绑定/构建依赖。 +- `./tools/build.sh --fresh`:ESP-IDF v5.5.2 / ESP32-S3 完整构建通过。应用大小 0x20fba0,最小应用分区 0x300000,剩余 31%。WebUI 重新优化并生成 SPIFFS 镜像。 +- `git diff --check`、JavaScript 语法、Workflow YAML 解析通过。 + +本地构建的元数据包含提交前工作区标志。正式 Release 由 Actions 从合并后的具体提交重新构建,不直接将本地提交前镜像作为云端验收结果。 + +## 发布条件 + +- Fork 分支和上游 PR 执行构建/回归,不发布正式版本。 +- 上游 `RMinte-AI/TianshanOS` 的 main 合并推送,构建与 WebUI 回归均成功后,依据 version.txt 自动创建 v0.5.2。 +- Release 绑定触发构建的 github.sha,中文正文来自 `docs/releases/v0.5.2.md`,不使用自动生成的英文提交摘要替代正文。 +- tools/check_release.py 要求 tag、version.txt、构建版本一致,并检查中文说明。没有对应说明的新版本不能静默发布。 +- 若同版本 Release 已存在,main 流程保持既有的跳过行为,不覆盖正式版本。发布新版本需同步更新版本与说明。 +- 本轮仅提交和提 PR,不自行合并,也不提前创建 v0.5.2 标签或 Release。 + +## 残余验证 + +主机模拟与云端编译无法证明真实 TLS 握手、设备会话吊销、断电/NVS 页回收、历史配置升级、Linux 进程组、SFTP/SCP、DNS 取消边界、三模型联动及长期资源趋势。具体矩阵见 `docs/CERTIFICATE_FIX_REPORT.md` 与 `docs/runtime-repair/VERIFICATION.md`。这些限制在中文发布说明中保留。 + +## 2026-09-25:未合并 PR 的 WebSocket 增量 + +本节更新上述首次提交记录;版本和发布触发条件不变。新增按需采集、定向发送、事件节点保活/排空,以及 R1—R5 停止重试、SSH 终态预留、日志代次和公平调度修复。 + +- 本轮提交前再次执行 `bash tests/ws_subscriptions/run_reviewer.sh`、`bash tests/ws_subscriptions/run_host.sh` 与 `python3 tests/release/test_release.py`;实际生产 C 回归与发布条件检查通过。 +- 修复前的未提交源码已归档并校验哈希,`run_reviewer_baseline.sh` 可重放五项反例。当前代码回归检查最终模拟发送边界,未以独立逻辑副本或测试数量代替行为验收。 +- 修复后运行时、证书及前端回归通过;Node 38 项、Chrome 中英文 38 项。浏览器使用模拟服务,不是与设备端 C 联机测试。 +- 最终生产源码由 ESP-IDF v5.5.2 在隔离构建目录编译链接通过:镜像 `0x213450` 字节,最小应用分区仍余 31%。提交前检查源文件哈希与这次构建证据一致;本轮更新发布文档未改动生产源码。 +- 完整行为、命令、日志、基线与设备验收清单见 [Reviewer 修复记录](../repair/ws-subscriptions/reviewer-fixes/README.md)。其中“未提交/未推送”描述修复交付时点;本次按用户后续授权提交并更新原 PR。 +- 新 PR head 的 Actions 结果须单独查看,不沿用旧 head `35238b4` 的绿灯。PR 事件只构建,合并 main 后才有发布资格。 + +这些主机与构建结果不证明真实 TCP、ESP32 双核并发、最大设备负载、长期堆碎片和栈水位已验收;现有 `/ws` 独立认证/主题授权缺口不属于本轮修复。 + +## 2026-09-25:F1/F2 增量 + +基于 PR head `bb0958c`,新增普通 SSH 输出接受后的失败结算及独立保护通知容量。版本、外部消息类型/字段、硬件保护和发布工作流保持不变。 + +- 冻结真实源码及哈希,相同 F1/F2 断言在修复前失败、修复后通过;覆盖迟到失败、回调早于返回、目标部分失败、终态顺序、容量耗尽、有限重试、busy/timeout 后自行排空及持续竞争。见 [完整证据](../repair/ws-f1-f2/README.md)。 +- 本次提交前再次运行 F1/F2 与 R1—R5 生产 C 回归及发布条件测试,通过;源码哈希与修复后的固件构建证据一致。 +- 该修复轮已重新执行 WS、运行时、证书和中英文 WebUI 回归;固定 ESP-IDF v5.5.2 本地构建成功,应用大小 `0x213f70`,分区余 31%。没有用旧 PR CI 替代新 head 的验证。 +- 保护配额为四条转换和一条周期通知、合计 5 KiB 常驻缓冲,非保护消息共享总 1 MiB 的剩余部分。关键入队拒绝最多尝试 300 次;永久拥塞或断线仍可能无法送达,失败会结算并记录。exec 输出观察失败不代表后台远端操作已取消。 +- 修复记录中“未提交、未更新 PR”描述当时本地交付状态;用户随后授权本次提交并更新原 PR。没有合并、发布或设备操作,仍需实机检查双核并发、慢连接、保护负载、长期堆和栈水位。 diff --git a/docs/releases/v0.5.2.md b/docs/releases/v0.5.2.md new file mode 100644 index 0000000..a18591e --- /dev/null +++ b/docs/releases/v0.5.2.md @@ -0,0 +1,69 @@ +# TianShanOS v0.5.2 + +本版本集中修复证书与 HTTPS 启动、自动化规则保存、SSH 后台任务与日志监控、WebSocket 展示采集与发送生命周期,以及 Web 管理界面的提示与操作结果判断。目标平台为 ESP32-S3,构建使用 ESP-IDF v5.5.2。 + +## 证书、时间与 HTTPS + +- 修复网页安装设备证书和 CA 证书时 PEM 长度不正确的问题,保留解析、公私钥匹配和容量检查;分别说明缺少私钥、密钥不匹配、解析错误及存储失败。 +- 证书有效期统一使用 UTC 计算,区分待校时、尚未生效、有效与过期。证书材料安装、证书有效期和 HTTPS 实际运行状态分别展示,避免仅凭材料存在就显示服务可用。 +- 浏览器校时与 NTP 校时统一通知 HTTPS 启动协调逻辑。先安装后校时、先校时后安装均重新检查条件;重试有上限,用户主动停止后旧事件不会重新启动服务。 +- 使用一致性证书快照和材料版本,避免并发安装与读取交叉。运行中更换材料后明确提示待应用,活动连接使用的证书不与新存储材料混为一谈;本版不增加无中断证书热替换。 +- 修复通用服务管理器吞掉停止错误的问题。停止失败不会继续按“停止成功”执行重启。 + +## 自动化规则与配置保存 + +- 将规则编辑从“删除再添加”改为带版本核对的更新。冲突时保留用户草稿,不允许旧页面静默覆盖新配置;丢失写入响应时不自动重放保存。 +- 保留手动触发、允许手动触发、规则启用和仪表盘展示之间的区别。切换手动模式不会清空自动条件,保存配置本身不会启动任务。 +- 完善规则、条件、动作与重复执行参数的序列化,保留显式 false、缺失模板引用等信息。修复合法点号开头规则在重新加载后消失的问题。 +- 为 SD/NVS 保存增加阶段标记、读回校验及恢复处理。提交结果无法确认时停止自动准入;备份同步失败不再伪装成全部成功,也不回退到陈旧配置。 +- 修复旧执行与新配置并存时的所有权、取消、删除及登记回收问题。停止采用协作退出,尚未完成时明确返回等待或失败,不强制删除仍持有资源的执行任务。 + +## SSH 服务、日志与资源释放 + +- SSH 认证前统一验证主机密钥。未知或变化的主机指纹需要明确确认,不能直接使用旧的模糊信任标记继续认证。 +- 查询、启动、停止和监控使用实例身份与运行代次。旧请求、旧取消和迟到的就绪消息不能影响新实例;取消观察不等于停止远端服务。 +- 普通页面状态轮询读取缓存,避免持续重新建立 SSH 连接;明确核实时才查询远端。断网后的就绪恢复必须属于同一个已确认实例。 +- 对连接、认证、执行、输出及关闭设置总时间预算,完善取消和错误路径的资源释放。同步 DNS 调用仍受底层解析行为限制,不承诺瞬时取消。 +- 受管服务停止前核对进程身份,停止其对应进程组;去除基于相邻 PID 的猜测。启动或停止结果不明时显示未知,不自动重复执行命令。 +- 原始日志完整输出,缓存使用有界预览并标明截断;改善 UTF-8、ANSI 和并发日志处理,减少认证噪声及内部敏感诊断输出。显式用户日志内容仍按原功能记录。 + +## Web 管理界面与操作结果 + +- 补齐中英文提示和参数,减少翻译键、内部枚举、变量与工程错误直接出现在主要提示中。真实文件名、路径、命令及远端原始输出保留原文。 +- 按具体接口契约判断成功。HTTP 错误保留原因;退出登录区分本地凭据清除与服务端响应确认,迟到退出结果不影响新登录。 +- 上传、下载、删除和配置应用区分成功、部分失败、验证失败及结果未知;下载提示只说明已向浏览器发起请求,不声称文件已经落盘。 +- 修复首次页面重复初始化、重复订阅及离开页面后的迟到更新。初始化失败可重试,旧页面只清理自己的订阅和资源。 +- 上传固定目的目录,验证结果绑定文件与上传代次;旧验证不能恢复应用按钮。同一路径重叠写入、无法确定最终内容时,要求重新上传验证,不自动重放上传。 +- 配置应用按当前有效尝试更新提示,旧成功、旧错误和旧 finally 不覆盖新结果、不关闭新弹窗。弹窗关闭后仍保留带路径和尝试编号的任务记录。 +- 上传结果与文件列表刷新结果分开呈现;旧目录响应不能覆盖当前目录。修复 Toast 定时器和重试成功被旧错误遮住的问题,动态结果以安全文本输出。 +- 完善 SSH 终态、终端恢复确认与资源加载失败重试,以及 LPMU 可达性、检测未知状态的提示。不修改硬件保护策略,也不以自动电源脉冲掩盖未知结果。 + +## WebSocket 采集、发送与停止 + +- 仪表盘及其他状态主题按有效订阅和到期时间采集。最后一个订阅者离开后停止启动新的展示采集;未到发送周期时不先读取和组包,同一批次共享所需指标。底层供电保护、风扇控制和必要传感器采样频率不变。 +- 修复每个主题订阅触发一次全体广播的问题。主题消息只序列化一次,再发往对应连接;连接身份与订阅代次在发送前复核,断线、文件描述符复用和重新订阅不会让旧消息发送给替代会话。原全局告警仍保留广播语义。 +- 采集前联合预留消息槽、发送描述符和字节预算。容量不足时保留待服务资格,不反复执行注定无法发送的采集;跨轮次轮转主题,避免持续负载下部分主题长期得不到更新。有限消息池和发送队列不会无限增长。 +- 停止分为拒绝新业务、暂停遥测、等待生产者收尾和排空已接受结果。活跃任务、停止超时或失败会逐层返回,保留发送 worker、资源和登记表,允许之后重试;没有新业务消息时,已接受结果仍继续推进。事件注销等待在途回调退出,不再把注销返回视为回调已全部结束。 +- SSH Shell 只有当前会话和轮询任务就绪后才报告 connected。任务创建失败、启动中关闭及迟到状态不会覆盖终态;接受 Shell/exec 任务前预留关键结果容量,容量不足明确拒绝。SDK 入队失败保留关键结果并退避重试,不重新执行远端命令;连接断开和实际发送失败仍可能导致结果无法送达。 +- SSH 普通输出在本地接受后,后续入队、发送和目标失效也反馈给所属会话;终态等待前序输出结算。已知输出不完整时明确报错,不再显示正常结束,也不向已成功的接收者重复广播。exec 网页观察结束不代表远端命令已取消或确定执行失败,后台仍遵循原业务规则。 +- 全局电压保护通知使用独立配额:四条状态转换和一条周期/调试通知,各 1 KiB,消息对象、目标描述符和字节预算均与普通日志隔离。已接受转换保持顺序,不用新状态覆盖旧转换;超载明确记录失败,通知回调不等待网络。关键通知只有在 SDK 明确拒绝入队时重试,最多 300 次、每次间隔至少 100 ms;实际 socket 失败不重发不确定帧。 +- 角色切换同步日志资格,排队日志绑定原订阅代次。日志切到终端/SSH、取消后重新订阅,均不会恢复旧日志的发送资格。 +- 总消息缓冲仍限制为 1 MiB,其中保护通知独占 5 KiB 常驻缓冲,其他消息共享剩余预算;exec 任务接受前预留最多 512 KiB,Shell 预留 4 KiB。预留会占用堆和可用发送容量,资源不足或上一结果尚未排空时,新任务可能被暂时拒绝。本版未新增 `/ws` 独立认证或主题授权,定向发送不等同于补齐该安全边界。 + +## 升级与兼容性说明 + +- 升级前请备份规则、SSH 主机/命令及相关配置。本版本没有新增分区,也不会主动清空 NVS 或替用户重新签发证书。 +- 同名加密配置包、旧单文件规则和部分镜像来源保持只读保护;并非所有历史配置格式都支持直接网页修改。 +- 旧固件仅留下单 PID、无法核实身份的活跃进程不会被新版本猜测性终止。需要操作人员先确认旧实例退出,再交由新版本接管。 +- 新后端的规则写入要求版本信息;使用旧缓存页面可能不能完成写入,升级后应刷新管理页面。固件与 WebUI 镜像应配套升级。 +- ready 表示已取得对应实例的日志就绪证据,不代表推理服务持续健康,也不是性能测试结论。 + +## 验证边界 + +已补充生产函数回归、模拟存储故障与并发测试,以及实际网页入口的中英文浏览器测试;构建与发布由本次提交对应的 GitHub Actions 执行。测试详情保存在仓库的证书、运行时、提示语修复记录及 [WebSocket 修复记录](https://github.com/RMinte-AI/TianshanOS/blob/main/docs/repair/ws-subscriptions/reviewer-fixes/README.md),以及 [F1/F2 后续修复记录](https://github.com/RMinte-AI/TianshanOS/blob/main/docs/repair/ws-f1-f2/README.md) 中。 + +本版本未将模拟测试等同于真实设备验收。实际 TLS 握手和证书切换、真实 SSH/SFTP/SCP、板卡断电恢复、旧配置升级、三模型联动、长期堆内存与时延,以及 WebSocket 的双核调度、慢连接/RST/LRU、反复启停和 worker 栈水位仍需部署环境验证。请先在可控设备上验收,再安排生产升级。 + +## 固件附件 + +Release 附带应用固件 `TianShanOS.bin`、WebUI 文件系统 `www.bin`、bootloader、分区表、OTA 初始数据及刷写参数(以该次构建实际附件为准)。本 Release 发布流程不连接设备,不自动刷机或重启。 diff --git a/docs/repair/ssh-poll-stack/README.md b/docs/repair/ssh-poll-stack/README.md new file mode 100644 index 0000000..d30b9db --- /dev/null +++ b/docs/repair/ssh-poll-stack/README.md @@ -0,0 +1,109 @@ +# PR42 ssh_poll 栈预算与 WithCaps 释放修复(2026-09-28) + +## 状态与范围 + +本地回归、固定 SDK 正式/诊断构建及两版各10轮真机 SSH 验收已完成,最后的设备离线首次加载与 J1 真通知也已补齐。正式候选已恢复。最低观测剩余栈分别为3876/3644 bytes,所测负载未复现原溢出;不扩张为任意负载安全或绝对零泄漏。详见文末最新结果与 `device-final/`。以下阶段记录保留历史顺序。 + +基线 HEAD `3a19128d8638771c958fe47df1d6a7d339a10a4c`,分支 `fix/v0.5.2-reliability-and-prompts`。起始无 tracked 修改;已有 `output/`、`tmp/`、`docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt` 保留。适用用户提供 AGENTS 规则;本仓及所改目录未发现额外 AGENTS 文件。 + +生产仅修改 `components/ts_webui/src/ts_webui_ws.c`:定义 `SSH_POLL_STACK_SIZE 8192`,Shell poller 创建参数使用该常量,退出改 `vTaskDeleteWithCaps(NULL)`。输出缓冲仍 2048,优先级仍 5,PSRAM 分配不变。没有修改前端、协议、operation、TX、SSH 驱动、保护、版本或发布配置。额外栈成本为单实例 4096 bytes PSRAM。 + +## 原始故障与静态检查 + +`crash.txt` 是本轮修改前真实设备故障摘录:Shell opened 后 `ssh_poll` stack overflow,继而软件重启。使用原 ELF 解析为 FreeRTOS `vApplicationStackOverflowHook`;回溯尾部 CORRUPTED,不能从该回溯推出最早出错的业务帧。原源码快照 `/tmp/ssh-poll-before.c`,哈希见 manifest.json,可由上述 HEAD 对照。 + +已检查: + +- poller 以 `sizeof(buf)-1` 即 2047 传入 `ts_ssh_shell_read`。 +- `ts_ssh_shell_read` 原样把 size 传给 libssh2;项目内 channel.c 的 `_libssh2_channel_read` 循环限定 `bytes_read < buflen`,复制长度不超过 `buflen-bytes_read`。 +- `ssh_send_output` 先取得原 operation 输出票据,再分配 len+1,复制 len 字节,在 buf[len] 放终止符;该 poller 的 len 来源受上面的 read 长度限制。 +- cJSON 使用终止字符串;output_finish 复制 JSON 到原有消息对象,再按原投递身份结算。不修改 caller buf。资源关闭、executor_done、task delete 顺序未变。 +- 未发现这一直接路径针对 caller buf 的明确越界证据。这不是对整个 libssh2 或全部运行时内存安全的证明。 + +因此实施用户指定的 8192 预算方案,而不是声称静态检查已排除所有内存破坏。 + +## 官方 SDK 删除契约与限制 + +固定 `/Users/massif/esp/v5.5.2/esp-idf`:`components/freertos/esp_additions/include/freertos/idf_additions.h` 明确 WithCaps 栈单位为 bytes,必须由 vTaskDeleteWithCaps 删除。既有 FreeRTOS 头链提供声明,两份完整构建均无需增加 include。 + +SDK `esp_additions/idf_additions.c` 表明普通 vTaskDelete 无法释放 WithCaps 静态分配的 TCB/stack。本次修正调用配对。self-delete 在 SDK 内创建短暂清理任务后挂起原任务;失败时 SDK abort。这是官方实现,不是本轮新增自定义任务或 wrapper。真机采样需允许清理任务得到调度后再判断残留;不能把主机删除替身当成 SDK 内存释放证明。 + +## 测试变更与结果 + +复用 `tests/ws_subscriptions/test_operation_adapter.c`,包含实际生产 WS/control/TX 实现: + +- 静态断言常量 8192,创建边界断言 WithCaps、8192、PSRAM。 +- WithCaps 删除边界断言 self-delete、executor 已退出、仍可取得的原上下文 shell/session 已清空。 +- 新增 10 轮 Shell 创建/退出,逐轮必须调用 WithCaps delete;排空后 OP_FREE、零 refs/executors 和零 tracked allocation。 +- 保留原创建失败/分配失败扫描与所有生命周期断言。 + +`before.txt`:修改生产前,创建参数断言在实际 4096 参数处失败(不是编译/依赖错误)。之后补充常量静态断言。`after.txt`:同一创建参数断言及新增删除/重复退出断言通过。它证明参数与资源流程,不是模拟 ESP32 栈安全。 + +执行环境:`IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf`,`DEVELOPER_DIR=/Library/Developer/CommandLineTools`。 + +| 入口 | 本轮结果与行为边界 | +| --- | --- | +| `python3 tests/ws_subscriptions/run_project_v3.py`(V3_RESULTS 指向 results) | 全部入口 exit 0;host/operation/adapter/control/reviewer/F1-F2/runtime/certificate/shell_driver/Node/双语跨层。覆盖 R1–R5、F1/F2、G1/G2、V1/V2、H1/J1 有效回归;见 results/host.json 和逐项日志 | +| `npm test --prefix tests/prompts`(上述 runner 内) | 40 通过,含 J1 实际输入/显示状态测试 | +| `python3 tests/ws_subscriptions/run_project_v3.py --browser` | Chrome 38 通过,双语 C→JS→C Chrome 跨层通过,见 results/browser.json | +| `npm run test:xterm --prefix tests/prompts` | 4 通过;真实 xterm,禁止外部 origin,网络记录 requests-source-*.json | +| 同一 browser runner,PROJECT_WEB_ROOT 指向候选 web_optimized | 浏览器及双语跨层通过,见 optimized/ | +| `PROJECT_WEB_ROOT=.../web_optimized node --test tests/prompts/xterm-offline.test.cjs` | 双语真实 xterm 首次离线加载/输入/J1/退出通过,见 optimized-xterm.txt 和 candidate/requests-*.json | +| `git diff --check` | 通过 | + +首次构建因沙箱拒绝 SDK psutil 进程枚举、Chrome 因沙箱启动失败;随后在获准的沙箱外本地环境重跑通过,没有更换 SDK/测试依赖。源码和构建输入自构建开始后未再修改;后续只补测试常量断言并重跑受影响主机/跨层测试。 + +## 两份构建与静态资源 + +- 正式候选:`/tmp/tianshan-ssh-stack-candidate/build`;App 0x215120,分区 31% 空余。 +- 诊断版:`/tmp/tianshan-ssh-stack-diagnostic/build`;App 0x259ee0,分区 22% 空余。 +- SDK 均 v5.5.2、ESP32-S3,独立完整 build;各目录 build.sh 保存精确构建命令。 +- 正式配置保留原 canary;诊断临时 sdkconfig 启用 `FREERTOS_CHECK_STACKOVERFLOW_CANARY`、`FREERTOS_WATCHPOINT_END_OF_STACK`、`COMPILER_STACK_CHECK_MODE_ALL`、`HEAP_POISONING_LIGHT`。正式 sdkconfig 未改。此处 sdkconfig-evidence.txt 仅证据,不是默认构建配置。 +- 固定 SDK 的 Kconfig/端口实现未发现上述 watchpoint 对本目标 PSRAM stack 的禁用条件,诊断配置实际进入 sdkconfig.h 并编译通过;硬件触发有效性未实测。watchpoint 只监测栈尾区域,且最多占用约 60 bytes,不是任意越界探测器。 +- 两份 TianShanOS.bin/www.bin/ELF 哈希见各自 assets.json。两份 xterm JS/CSS/fit 的优化原文件逐字节等于 vendor 源,gzip 解压也相等,详见 manifest.json。 +- 两份均执行 `tests/ws_subscriptions/verify_project_assets.py`,由最终 web_optimized 重建 SPIFFS 与实际 www.bin 逐字节一致,打包无容量溢出。 +- flasher_args.json 均含 0x6a0000:www.bin。构建日志中的 flash 用法仅 SDK 提示,本轮未执行 flash。 + +## 初始待授权真机验收计划(历史,后续执行结果见下文) + +1. 先确认可输入命令的 UART0 通道。当前 USB Serial/JTAG 已用于收日志,但当前固件 CLI stdin 为 UART0;装了 CH344 驱动不等于 CH344 通道已连接。不能在活动远端 Shell 中输入 system --tasks 冒充设备 CLI 查询。 +2. 获得刷机授权后分别记录候选/诊断固件哈希,完整刷 App+www,保持串口日志。 +3. welcome 后、有限 200 行输出过程中与结束后、pwd/uname 输入后、resize 后、退出前采样 system --tasks 的 ssh_poll STACK。 +4. 本 SDK Xtensa `StackType_t` 为 uint8_t,high-water 计算除 sizeof(StackType_t),本项目直接打印 usStackHighWaterMark,故单位为 **bytes**。记录全程最低值,目标至少约 2048 bytes;仅几百 bytes 或继续溢出则停止并报告,不自行再增栈。 +5. 至少 10 轮 connect/welcome/input/Ctrl+\\/closed,每轮退出清理后采集 tasks 与 memory,检查 ssh_poll 消失及 PSRAM/heap 趋势。当前产品没有公开 operation ledger 查询接口:OP_FREE 直接断言目前仅有主机证据,不能用 tasks 消失冒充真机 ledger 读取。若要求真机直接读 ledger,需要另行确定观测手段,本轮不加生产接口。 +6. 诊断版重复全部负载,检查 canary/watchpoint/heap poison/assert/panic/watchdog/load-store 错误;出现任何项均不能宣布关闭。 + +**本轮没有新真机结果,没有 high-water 数值,也没有真机 10 轮 PSRAM 释放证据。** 本地交付已准备好;只有完成上述授权验收后才可判断 8192 预算是否足够以及是否支持原始栈预算不足的根因解释。未提交、推送或更新 PR。 + +## 后续用户授权真机执行(阶段记录) + +用户在本地交付后明确授权刷机验收。候选版完整 flash App+www 成功,启动 ELF 前缀 2c29402b1 与候选 ELF 一致,12 服务正常。用户通过真实 Safari 完成 welcome、200 行有限输出、pwd/uname、窗口调整及 Ctrl+\ 退出;10 轮连接/输入/退出均有用户确认及逐轮 API 观测,见 device-candidate。 + +UART0 尚无输入通道,复用现有只读 system.tasks API:与 system --tasks 同为 uxTaskGetSystemState/usStackHighWaterMark,单位 bytes,不改变生产接口。全程最低值 3876 bytes(第 10 轮);每轮退出后 ssh_poll 数为 0,无检测到的 panic/stack overflow/assert/watchdog。PSRAM 空闲从第 1 轮 7614416 到第 10 轮 7613736 bytes,中间第 8 轮下降后第 9 轮回升;未出现每轮一个任务栈大小的泄漏,但小幅净差仍不能证明零泄漏,也不能直接读取真机 operation FREE。此轮未作堆分配归因。 + +诊断版验收正在进行,最终根因关闭结论仍保留。 + +## 诊断真机结果(2026-09-28,自动阶段完成) + +正式候选 10 轮由用户通过 Safari 完成。诊断版第 1 轮用户完成 welcome、200 行输出、pwd/uname、resize、Ctrl+\\ 和本地 help;用户随后明确授权代理自动完成余下测试。第 2–10 轮使用 Node 原生 WebSocket 连接设备原有 WS handler,真实设备再连接 10.10.99.98,只执行独立 echo 标记并发送既有 ssh_disconnect。该九轮是**真实设备/真实 SSH 的协议自动验收,不是九轮浏览器键盘验收**;前述人工轮覆盖了实际 UI。 + +自动脚本第一尝试因未剥离 bracketed-paste ANSI 控制字符而未匹配 echo 输出,正常断开后停止,没有计为通过。后续脚本保存原始输出并剥离 CSI,仅接受一整行等于唯一 marker(不能将命令回显当成执行结果)。九轮均收到 connecting→connected→disconnecting→closed,验证了 echo 返回与 poller 消失。脚本见 device-diagnostic/rounds.mjs;凭据从环境读取,未写入脚本或证据。 + +- 诊断全程最低观测剩余栈 **3644 bytes**(第 6 轮主动阶段采样);后台每 2 秒采样最低 3984 bytes。必须合并两种采样,不能只取定时器数据。candidate 最低 3876 bytes。8192 减上述水位分别约 4548/4316 bytes,支持实际用栈超过原 4096 预算;水位不是对每条指令的精确峰值追踪。 +- 所有诊断轮次退出后无 ssh_poll;最终内部 free 25671 bytes 与第 1 轮相同。PSRAM 第 1 轮后 7596844,自动第 6 轮 7587612、第 7 轮 7593832、第 10 轮 7594840,最终空闲 7595232 bytes。存在波动与回升,未呈逐轮固定下降,未出现 WithCaps 栈/TCB 规模的重复泄漏;最终比初轮少 1612 bytes,未做分配归因,不能宣称绝对零泄漏。 +- 本次保存的诊断日志没有 stack/canary/watchpoint/heap corruption/assert/panic/watchdog/load-store 错误。增强检测只覆盖本次负载及工具检测范围,不是形式化排除任意内存破坏。 +- 真机无公开 operation ledger 读取入口;FREE/ref 闭合由生产 C 主机回归直接验证,真机以任务消失、重复创建成功和内存趋势间接验证,不混淆证据层级。 +- 两版最低余量均超过约 2 KB 门槛,实际负载未再次触发原崩溃,证据支持原 4 KB 栈预算不足。可进入后续最终真机验收;全系统/J1 真机电源告警、完全断公网首载等不因本轮通过自动判定完成。 + +测试后恢复正式候选 App+www,启动复核记录另见 device-candidate/restore-*。没有提交、推送、更新 PR 或改动额外生产代码。 + +## 最后两项真机补验(2026-09-28,正式候选) + +证据位于 `device-final/`。没有新增生产修改、刷机或配置变更。 + +1. **禁止公网的首次加载**:Playwright 启动全新 Chrome context,无既有缓存/登录,禁用 Service Worker;路由仅放行 `http://10.10.99.97`,其他 origin 一律 abort。用户仅完成登录,后续操作由代理通过 CUA 执行。未注入 Terminal/FitAddon/WebSocket 或伪造服务器响应。实际三个 vendor URL 均来自设备,构造器存在、终端成功初始化,所有 HTTP 请求无外部 origin,pageerror 为零;设备返回的三个资源字节与源码完全一致。见 network.json、health-assets.json。 +2. **J1 真事件、真 SSH**:设备正常电压约 20.5V,保护 NORMAL、触发次数0。通过实际 Web Terminal 执行 `voltprot --status` 后执行 `voltprot --debug`,进入已授权 SSH 主机。真实 `power_event/debug_tick` 在 SSH 中显示,活动阶段无新增 `tianshan>`,sshMode 保持 true。实际键盘输入 `echo TIANSHAN_J1_REAL_PASS` 产生 ssh_input,收到独立远端返回行;随后 Ctrl+\\ 产生 ssh_disconnect,收到 disconnecting→closed 后才回到本地。接着本地 echo 产生 terminal_input 并正常返回。离开页面后终端实例消失,重新进入后连接正常,vendor 请求累计仍仅三个。退出后设备 tasks 无 ssh_poll。 +3. **调试结束边界**:本次浏览器操作和取证超过8–10秒提前关闭目标,使用原命令既有30秒自动关闭,没有在自动关闭后再次切换以免重新开启。双 WebSocket 共记录60个 debug_tick(两个连接各接收同一批30秒通知),后续本地命令、离开/重新进入期间计数保持60,未再增加。未触发低压、关机或阈值修改。这里验证安全 debug_tick 显示路径,并不声称真实低压关机链路经过测试。 +4. **测试干扰与边界**:最初旧 Safari 与新 Chrome 同时停留终端页,收到明确 `session_closed: Another terminal session requested`;将旧 Safari 移至系统页后再执行 J1。此干扰与原 stack overflow 不同。当前补验没有重新接通串口监控,不能据此声称本段串口无错误;此前两版10轮串口/任务/水位证据仍见对应目录。当前段以浏览器消息、真实echo、设备状态和任务回收为证。 + +本轮上述实际消息/状态/网络断言通过。此结果补齐了先前列出的离线真机首载和J1真机通知两项,不能扩张为全系统无缺陷、任意负载无泄漏或直接读取真机 operation 账本。尚未提交、推送或合并。 diff --git a/docs/repair/ssh-poll-stack/after.txt b/docs/repair/ssh-poll-stack/after.txt new file mode 100644 index 0000000..540987e --- /dev/null +++ b/docs/repair/ssh-poll-stack/after.txt @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=94 diff --git a/docs/repair/ssh-poll-stack/before.txt b/docs/repair/ssh-poll-stack/before.txt new file mode 100644 index 0000000..b4ce45e --- /dev/null +++ b/docs/repair/ssh-poll-stack/before.txt @@ -0,0 +1,2 @@ +Assertion failed: (!strcmp(n,"ssh_poll") && stack==8192 && caps==MALLOC_CAP_SPIRAM), function adapter_create_caps, file test_operation_adapter.c, line 138. +tests/ws_subscriptions/run_operation_adapter.sh: line 11: 36726 Abort trap: 6 "$build/adapter" diff --git a/docs/repair/ssh-poll-stack/candidate/assets.json b/docs/repair/ssh-poll-stack/candidate/assets.json new file mode 100644 index 0000000..b9217ee --- /dev/null +++ b/docs/repair/ssh-poll-stack/candidate/assets.json @@ -0,0 +1,41 @@ +{ + "index.html": { + "source_sha256": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "optimized_sha256": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "gzip_sha256": "808c43f54d431ec28af120225bc2e9176af7977075be881b6948c4db7d90f7ee", + "optimized_bytes": 26676 + }, + "js/terminal.js": { + "source_sha256": "5d77a7181b6127699e098f22d3c872f5e31daaa700436b6fa928f34b6aa33e52", + "optimized_sha256": "6759587f527a0c37aaf8b13f6b5ffc017a452954cd23b780b5d6254488f939dc", + "gzip_sha256": "5ce7a22c1176722e2c85b89756d596fd170ae4557a2b0dd66de27a47432f2acf", + "optimized_bytes": 20066 + }, + "js/lang/zh-CN.js": { + "source_sha256": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "optimized_sha256": "81b0fed5b0ac73d51d9c37204c9f62e035a79bbf5b5610d37fc8a936faf9fd64", + "gzip_sha256": "9d1d0eed6025cd7839e8a9c650bfadb600fdd50f48a662305f9189e06e485a38", + "optimized_bytes": 137314 + }, + "js/lang/en-US.js": { + "source_sha256": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "optimized_sha256": "e9963046086616fecc9ba662df94e736a98c1430865e0caa47292b3690ca0ad0", + "gzip_sha256": "2af0a582c56d9f1561bd84c65cfb5060c123dc244360da762049a0fb49f08336", + "optimized_bytes": 143161 + }, + "build": { + "TianShanOS.bin": { + "sha256": "633080a1ca2f23a7de7f0fd6ca47de81c93227fc8b3ef5bae91513e41c2bc314", + "bytes": 2183456 + }, + "www.bin": { + "sha256": "37dca9abb5a6c3c91fffade1fc0e7ea44a4ba3f35592e89d72340654eeb8b9c9", + "bytes": 3145728 + }, + "TianShanOS.elf": { + "sha256": "2c29402b17a8c32c9167151666f0533737f704a549d1ad9df1895b45401f79f5", + "bytes": 18286832 + } + }, + "spiffs_regeneration": "byte-identical from verified optimized directory" +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/candidate/build.log b/docs/repair/ssh-poll-stack/candidate/build.log new file mode 100644 index 0000000..ffaf942 --- /dev/null +++ b/docs/repair/ssh-poll-stack/candidate/build.log @@ -0,0 +1,1697 @@ +Checking "python3" ... +Python 3.12.4 +"python3" has been detected +Activating ESP-IDF 5.5 +Setting IDF_PATH to '/Users/massif/esp/v5.5.2/esp-idf'. +* Checking python version ... 3.12.4 +* Checking python dependencies ... OK +* Deactivating the current ESP-IDF environment (if any) ... OK +* Establishing a new ESP-IDF environment ... OK +* Identifying shell ... zsh +* Detecting outdated tools in system ... Found tools that are not used by active ESP-IDF version. +For removing old versions of riscv32-esp-elf, cmake, xtensa-esp-elf, openocd-esp32, esp-rom-elfs, xtensa-esp-elf-gdb, riscv32-esp-elf-gdb use command 'python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall' +To free up even more space, remove installation packages of those tools. +Use option python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall --remove-archives. +* Shell completion ... Autocompletion code generated + +Done! You can now compile ESP-IDF projects. +Go to the project directory and run: + + idf.py build +ESP-IDF v5.5.2 +Executing action: all (aliases: build) +Running cmake in directory /private/tmp/tianshan-ssh-stack-candidate/build +Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DPYTHON=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python -DESP_PLATFORM=1 -DSDKCONFIG=/tmp/tianshan-ssh-stack-candidate/sdkconfig -DCCACHE_ENABLE=0 /Users/massif/TianshanOS"... +-- Found Python3: /opt/anaconda3/bin/python3.12 (found version "3.12.4") found components: Interpreter +-- IDF_TARGET is not set, guessed 'esp32s3' from sdkconfig '/tmp/tianshan-ssh-stack-candidate/sdkconfig' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +NOTICE: +Following dependencies have new versions available: +Dependency "espressif/libpng": "1.6.54" -> "1.6.58~2" +Dependency "espressif/mdns": "1.9.1" -> "1.13.1" +Dependency "espressif/zlib": "1.3.1" -> "1.3.2~1" +Consider running "idf.py update-dependencies" to update your lock file. +NOTICE: Processing 7 dependencies: +NOTICE: [1/7] espressif/esp_jpeg (1.3.1) +NOTICE: [2/7] espressif/esp_websocket_client (1.5.0) +NOTICE: [3/7] espressif/led_strip (3.0.3) +NOTICE: [4/7] espressif/libpng (1.6.54) +NOTICE: [5/7] espressif/mdns (1.9.1) +NOTICE: [6/7] espressif/zlib (1.3.1) +NOTICE: [7/7] idf (5.5.2) +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-ssh-stack-candidate/sdkconfig +Loading defaults file /Users/massif/TianshanOS/sdkconfig.defaults... +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:54 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:56 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:64 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:66 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:82 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:84 line was updated to # === L2 NVS 加密配置(HMAC 方案)===n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:159 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:161 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:170 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:172 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:182 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:184 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:193 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:195 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:227 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpywtcf3_o:229 line was updated to # ============================================================================n +-- Compiler supported targets: xtensa-esp-elf +-- Found Python3: /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python (found version "3.12.4") found components: Interpreter +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS - Success +-- USING O3 +-- App "TianShanOS" version: 0.5.2+3a19128d.09281801 +-- Adding linker script /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esp_system/ld/memory.ld +-- Adding linker script /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esp_system/ld/sections.ld.in +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Web optimization enabled (minify + gzip) +-- Components: app_trace app_update bootloader bootloader_support bt ch405labs_esp_libssh2 cmock console cxx driver efuse esp-tls esp_adc esp_app_format esp_bootloader_format esp_coex esp_common esp_driver_ana_cmpr esp_driver_bitscrambler esp_driver_cam esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_isp esp_driver_jpeg esp_driver_ledc esp_driver_mcpwm esp_driver_parlio esp_driver_pcnt esp_driver_ppa esp_driver_rmt esp_driver_sdio esp_driver_sdm esp_driver_sdmmc esp_driver_sdspi esp_driver_spi esp_driver_touch_sens esp_driver_tsens esp_driver_twai esp_driver_uart esp_driver_usb_serial_jtag esp_eth esp_event esp_gdbstub esp_hid esp_http_client esp_http_server esp_https_ota esp_https_server esp_hw_support esp_lcd esp_local_ctrl esp_mm esp_netif esp_netif_stack esp_partition esp_phy esp_pm esp_psram esp_ringbuf esp_rom esp_security esp_system esp_timer esp_vfs_console esp_wifi espcoredump espressif__esp_jpeg espressif__esp_websocket_client espressif__led_strip espressif__libpng espressif__mdns espressif__zlib esptool_py fatfs freertos hal heap http_parser idf_test ieee802154 json log lwip main mbedtls mqtt newlib nvs_flash nvs_sec_provider openthread partition_table perfmon protobuf-c protocomm pthread rt sdmmc soc spi_flash spiffs tcp_transport touch_element ts_api ts_auth_layout ts_automation ts_cert ts_config ts_config_pack ts_console ts_core ts_drivers ts_event ts_hal ts_https ts_jsonpath ts_led ts_log ts_mempool ts_net ts_ota ts_pki_client ts_security ts_service ts_storage ts_webui ulp unity usb vfs wear_levelling wifi_provisioning wpa_supplicant xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/app_trace /Users/massif/esp/v5.5.2/esp-idf/components/app_update /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/bt /Users/massif/TianshanOS/components/ch405labs_esp_libssh2 /Users/massif/esp/v5.5.2/esp-idf/components/cmock /Users/massif/esp/v5.5.2/esp-idf/components/console /Users/massif/esp/v5.5.2/esp-idf/components/cxx /Users/massif/esp/v5.5.2/esp-idf/components/driver /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp-tls /Users/massif/esp/v5.5.2/esp-idf/components/esp_adc /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_coex /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ana_cmpr /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_bitscrambler /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_cam /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_dac /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gpio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gptimer /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2c /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2s /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_isp /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_jpeg /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ledc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_mcpwm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_parlio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_pcnt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ppa /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_rmt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdspi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_spi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_touch_sens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_tsens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_twai /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_uart /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_usb_serial_jtag /Users/massif/esp/v5.5.2/esp-idf/components/esp_eth /Users/massif/esp/v5.5.2/esp-idf/components/esp_event /Users/massif/esp/v5.5.2/esp-idf/components/esp_gdbstub /Users/massif/esp/v5.5.2/esp-idf/components/esp_hid /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_client /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_ota /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_lcd /Users/massif/esp/v5.5.2/esp-idf/components/esp_local_ctrl /Users/massif/esp/v5.5.2/esp-idf/components/esp_mm /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif_stack /Users/massif/esp/v5.5.2/esp-idf/components/esp_partition /Users/massif/esp/v5.5.2/esp-idf/components/esp_phy /Users/massif/esp/v5.5.2/esp-idf/components/esp_pm /Users/massif/esp/v5.5.2/esp-idf/components/esp_psram /Users/massif/esp/v5.5.2/esp-idf/components/esp_ringbuf /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esp_timer /Users/massif/esp/v5.5.2/esp-idf/components/esp_vfs_console /Users/massif/esp/v5.5.2/esp-idf/components/esp_wifi /Users/massif/esp/v5.5.2/esp-idf/components/espcoredump /Users/massif/TianshanOS/managed_components/espressif__esp_jpeg /Users/massif/TianshanOS/managed_components/espressif__esp_websocket_client /Users/massif/TianshanOS/managed_components/espressif__led_strip /Users/massif/TianshanOS/managed_components/espressif__libpng /Users/massif/TianshanOS/managed_components/espressif__mdns /Users/massif/TianshanOS/managed_components/espressif__zlib /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/fatfs /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/heap /Users/massif/esp/v5.5.2/esp-idf/components/http_parser /Users/massif/esp/v5.5.2/esp-idf/components/idf_test /Users/massif/esp/v5.5.2/esp-idf/components/ieee802154 /Users/massif/esp/v5.5.2/esp-idf/components/json /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/lwip /Users/massif/TianshanOS/main /Users/massif/esp/v5.5.2/esp-idf/components/mbedtls /Users/massif/esp/v5.5.2/esp-idf/components/mqtt /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/nvs_flash /Users/massif/esp/v5.5.2/esp-idf/components/nvs_sec_provider /Users/massif/esp/v5.5.2/esp-idf/components/openthread /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/perfmon /Users/massif/esp/v5.5.2/esp-idf/components/protobuf-c /Users/massif/esp/v5.5.2/esp-idf/components/protocomm /Users/massif/esp/v5.5.2/esp-idf/components/pthread /Users/massif/esp/v5.5.2/esp-idf/components/rt /Users/massif/esp/v5.5.2/esp-idf/components/sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/spiffs /Users/massif/esp/v5.5.2/esp-idf/components/tcp_transport /Users/massif/esp/v5.5.2/esp-idf/components/touch_element /Users/massif/TianshanOS/components/ts_api /Users/massif/TianshanOS/components/ts_auth_layout /Users/massif/TianshanOS/components/ts_automation /Users/massif/TianshanOS/components/ts_cert /Users/massif/TianshanOS/components/ts_core/ts_config /Users/massif/TianshanOS/components/ts_config_pack /Users/massif/TianshanOS/components/ts_console /Users/massif/TianshanOS/components/ts_core /Users/massif/TianshanOS/components/ts_drivers /Users/massif/TianshanOS/components/ts_core/ts_event /Users/massif/TianshanOS/components/ts_hal /Users/massif/TianshanOS/components/ts_https /Users/massif/TianshanOS/components/ts_jsonpath /Users/massif/TianshanOS/components/ts_led /Users/massif/TianshanOS/components/ts_core/ts_log /Users/massif/TianshanOS/components/ts_mempool /Users/massif/TianshanOS/components/ts_net /Users/massif/TianshanOS/components/ts_ota /Users/massif/TianshanOS/components/ts_pki_client /Users/massif/TianshanOS/components/ts_security /Users/massif/TianshanOS/components/ts_core/ts_service /Users/massif/TianshanOS/components/ts_storage /Users/massif/TianshanOS/components/ts_webui /Users/massif/esp/v5.5.2/esp-idf/components/ulp /Users/massif/esp/v5.5.2/esp-idf/components/unity /Users/massif/esp/v5.5.2/esp-idf/components/usb /Users/massif/esp/v5.5.2/esp-idf/components/vfs /Users/massif/esp/v5.5.2/esp-idf/components/wear_levelling /Users/massif/esp/v5.5.2/esp-idf/components/wifi_provisioning /Users/massif/esp/v5.5.2/esp-idf/components/wpa_supplicant /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- +-- ╔═══════════════════════════════════════════════════════════╗ +-- ║ TianShanOS v0.5.2+3a19128d.09281801 ║ +-- ║ ESP32 Rack Management Operating System ║ +-- ╚═══════════════════════════════════════════════════════════╝ +-- +-- Version: 0.5.2+3a19128d.09281801 +-- Major: 0 +-- Minor: 5 +-- Patch: 2 +-- Build: 3a19128d.09281801 +-- +-- Target: esp32s3 +-- Build type: +-- +-- Configuring done (6.1s) +-- Generating done (0.7s) +-- Build files have been written to: /tmp/tianshan-ssh-stack-candidate/build +Running ninja in directory /private/tmp/tianshan-ssh-stack-candidate/build +Executing "ninja all"... +[1/1343] Generating project_elf_src_esp32s3.c +[2/1343] Generating ../../ota_data_initial.bin +[3/1343] Generating /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esp_system/ld/memory.ld linker script... +[4/1343] Generating /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esp_system/ld/sections.ld.in linker script... +[5/1343] Copying web assets to build directory +[6/1343] Generating ../../partition_table/partition-table.bin +Partition table binary generated. Contents: +******************************************************************************* +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs,data,nvs,0x9000,48K, +nvs_keys,data,nvs_keys,0x15000,4K, +otadata,data,ota,0x16000,8K, +phy_init,data,phy,0x18000,4K, +ota_0,app,ota_0,0x20000,3M, +ota_1,app,ota_1,0x320000,3M, +storage,data,spiffs,0x620000,512K, +www,data,spiffs,0x6a0000,3M, +fatfs,data,fat,0x9a0000,64K, +******************************************************************************* +[7/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_utils.c.obj +[8/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_header.c.obj +[9/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_auth.c.obj +[10/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/util/ctrl_sock.c.obj +[11/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_internal.c.obj +[12/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_uri.c.obj +[13/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/xip_impl/mmu_psram_flash.c.obj +[14/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_ws.c.obj +[15/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_main.c.obj +[16/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport.c.obj +[17/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_socks_proxy.c.obj +[18/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali.c.obj +[19/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_sess.c.obj +[20/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_parse.c.obj +[21/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_txrx.c.obj +[22/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/system_layer/esp_psram.c.obj +[23/1343] Building C object esp-idf/esp_https_ota/CMakeFiles/__idf_esp_https_ota.dir/src/esp_https_ota.c.obj +[24/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/esp32s3/esp_psram_impl_octal.c.obj +[25/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_common.c.obj +[26/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ssl.c.obj +[27/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_oneshot.c.obj +[28/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp_adc_cal_common_legacy.c.obj +[29/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali_curve_fitting.c.obj +[30/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/esp32s3/curve_fitting_coefficients.c.obj +[31/1343] Linking C static library esp-idf/esp_https_ota/libesp_https_ota.a +[32/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp-tls-crypto/esp_tls_crypto.c.obj +[33/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/gdma/adc_dma.c.obj +[34/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp32s3/esp_adc_cal_legacy.c.obj +[35/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_platform_port.c.obj +[36/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_error_capture.c.obj +[37/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_monitor.c.obj +[38/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_filter.c.obj +[39/1343] Linking C static library esp-idf/esp_http_server/libesp_http_server.a +[40/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_continuous.c.obj +[41/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ws.c.obj +[42/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_legacy.c.obj +[43/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/sigma_delta_legacy.c.obj +[44/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_dma_legacy.c.obj +[45/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/esp_http_client.c.obj +[46/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rtc_temperature_legacy.c.obj +[47/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_mbedtls.c.obj +[48/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/timer_legacy.c.obj +[49/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/touch_sensor_common.c.obj +[50/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls.c.obj +[51/1343] Linking C static library esp-idf/esp_http_client/libesp_http_client.a +[52/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai.c.obj +[53/1343] Linking C static library esp-idf/tcp_transport/libtcp_transport.a +[54/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/pcnt_legacy.c.obj +[55/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/twai/twai.c.obj +[56/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai_onchip.c.obj +[57/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_common.c.obj +[58/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/esp32s3/touch_sensor.c.obj +[59/1343] Building C object esp-idf/esp_driver_tsens/CMakeFiles/__idf_esp_driver_tsens.dir/src/temperature_sensor.c.obj +[60/1343] Building C object esp-idf/esp_driver_sdm/CMakeFiles/__idf_esp_driver_sdm.dir/src/sdm.c.obj +[61/1343] Linking C static library esp-idf/esp_psram/libesp_psram.a +[62/1343] Building C object esp-idf/http_parser/CMakeFiles/__idf_http_parser.dir/http_parser.c.obj +[63/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_slave.c.obj +[64/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/i2s_legacy.c.obj +[65/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder.c.obj +[66/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/i2c/i2c.c.obj +[67/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_crc.c.obj +[68/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_copy.c.obj +[69/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_bytes.c.obj +[70/1343] Linking C static library esp-idf/esp_adc/libesp_adc.a +[71/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_common.c.obj +[72/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_simple.c.obj +[73/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_transaction.c.obj +[74/1343] Linking C static library esp-idf/esp-tls/libesp-tls.a +[75/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_transaction.c.obj +[76/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_init.c.obj +[77/1343] Linking C static library esp-idf/http_parser/libhttp_parser.a +[78/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_common.c.obj +[79/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_io.c.obj +[80/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sd_pwr_ctrl/sd_pwr_ctrl.c.obj +[81/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_mmc.c.obj +[82/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_host.c.obj +[83/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/mcpwm_legacy.c.obj +[84/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_cmd.c.obj +[85/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_master.c.obj +[86/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rmt_legacy.c.obj +[87/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_rx.c.obj +[88/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_platform.c.obj +[89/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_sd.c.obj +[90/1343] Building C object esp-idf/esp_driver_ledc/CMakeFiles/__idf_esp_driver_ledc.dir/src/ledc.c.obj +[91/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cmpr.c.obj +[92/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_std.c.obj +[93/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_com.c.obj +[94/1343] Linking C static library esp-idf/driver/libdriver.a +[95/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_tdm.c.obj +[96/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_sync.c.obj +[97/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_pdm.c.obj +[98/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_host.c.obj +[99/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_tx.c.obj +[100/1343] Linking C static library esp-idf/esp_driver_twai/libesp_driver_twai.a +[101/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub_transport.c.obj +[102/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub.c.obj +[103/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_fault.c.obj +[104/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_oper.c.obj +[105/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/packet.c.obj +[106/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub-entry.S.obj +[107/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/xt_debugexception.S.obj +[108/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_timer.c.obj +[109/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cap.c.obj +[110/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub_xtensa.c.obj +[111/1343] Linking C static library esp-idf/esp_driver_ledc/libesp_driver_ledc.a +[112/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_gen.c.obj +[113/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/lib_printf.c.obj +[114/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/mesh_event.c.obj +[115/1343] Linking C static library esp-idf/esp_driver_i2c/libesp_driver_i2c.a +[116/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig.c.obj +[117/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default_ap.c.obj +[118/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_common.c.obj +[119/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/regulatory/esp_wifi_regulatory.c.obj +[120/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_netif.c.obj +[121/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj +[122/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug_diagram.c.obj +[123/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default.c.obj +[124/1343] Linking C static library esp-idf/esp_driver_sdm/libesp_driver_sdm.a +[125/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug.c.obj +[126/1343] Building C object esp-idf/esp_driver_pcnt/CMakeFiles/__idf_esp_driver_pcnt.dir/src/pulse_cnt.c.obj +[127/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/esp32s3/esp_coex_adapter.c.obj +[128/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig_ack.c.obj +[129/1343] Linking C static library esp-idf/esp_driver_tsens/libesp_driver_tsens.a +[130/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/os_xtensa.c.obj +[131/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ap_config.c.obj +[132/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave.c.obj +[133/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/eloop.c.obj +[134/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32s3/esp_adapter.c.obj +[135/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave_hd.c.obj +[136/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_1x.c.obj +[137/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/comeback_token.c.obj +[138/1343] Linking C static library esp-idf/esp_driver_rmt/libesp_driver_rmt.a +[139/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/sta_info.c.obj +[140/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth_ie.c.obj +[141/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_common.c.obj +[142/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/pmksa_cache_auth.c.obj +[143/1343] Linking C static library esp-idf/esp_driver_sdspi/libesp_driver_sdspi.a +[144/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/bitfield.c.obj +[145/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_11.c.obj +[146/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-kdf.c.obj +[147/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-siv.c.obj +[148/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-gcm.c.obj +[149/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/dragonfly.c.obj +[150/1343] Linking C static library esp-idf/esp_driver_sdmmc/libesp_driver_sdmmc.a +[151/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_group5.c.obj +[152/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_ops.c.obj +[153/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_groups.c.obj +[154/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_master.c.obj +[155/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/wpa_common.c.obj +[156/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-tlsprf.c.obj +[157/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tlsprf.c.obj +[158/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ccmp.c.obj +[159/1343] Linking C static library esp-idf/sdmmc/libsdmmc.a +[160/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-tlsprf.c.obj +[161/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ms_funcs.c.obj +[162/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-prf.c.obj +[163/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-prf.c.obj +[164/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-prf.c.obj +[165/1343] Linking C static library esp-idf/esp_driver_i2s/libesp_driver_i2s.a +[166/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/md4-internal.c.obj +[167/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_common.c.obj +[168/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_common/eap_wsc_common.c.obj +[169/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/chap.c.obj +[170/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tprf.c.obj +[171/1343] Linking C static library esp-idf/esp_driver_mcpwm/libesp_driver_mcpwm.a +[172/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls.c.obj +[173/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap_common.c.obj +[174/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap.c.obj +[175/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth.c.obj +[176/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/mschapv2.c.obj +[177/1343] Linking C static library esp-idf/esp_driver_pcnt/libesp_driver_pcnt.a +[178/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_common.c.obj +[179/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/ieee802_11_common.c.obj +[180/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_mschapv2.c.obj +[181/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/pmksa_cache.c.obj +[182/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls_common.c.obj +[183/1343] Linking C static library esp-idf/esp_gdbstub/libesp_gdbstub.a +[184/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/ext_password.c.obj +[185/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/base64.c.obj +[186/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_pac.c.obj +[187/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap.c.obj +[188/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/uuid.c.obj +[189/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_ttls.c.obj +[190/1343] Linking C static library esp-idf/esp_driver_spi/libesp_driver_spi.a +[191/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpa_debug.c.obj +[192/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae.c.obj +[193/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/common.c.obj +[194/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa_ie.c.obj +[195/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpabuf.c.obj +[196/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa2_api_port.c.obj +[197/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_process.c.obj +[198/1343] Linking C static library esp-idf/esp_wifi/libesp_wifi.a +[199/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_parse.c.obj +[200/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_build.c.obj +[201/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/json.c.obj +[202/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_common.c.obj +[203/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_dev_attr.c.obj +[204/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps.c.obj +[205/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpas_glue.c.obj +[206/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae_pk.c.obj +[207/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa_main.c.obj +[208/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_owe.c.obj +[209/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_common.c.obj +[210/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_enrollee.c.obj +[211/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_eap_client.c.obj +[212/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast.c.obj +[213/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_hostap.c.obj +[214/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls.c.obj +[215/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpsk.c.obj +[216/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c.obj +[217/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa3.c.obj +[218/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wps.c.obj +[219/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/rc4.c.obj +[220/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa.c.obj +[221/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c.obj +[222/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_defaults.c.obj +[223/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-wrap.c.obj +[224/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpbkdf2.c.obj +[225/1343] Linking C static library esp-idf/esp_coex/libesp_coex.a +[226/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_objects.c.obj +[227/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/des-internal.c.obj +[228/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-unwrap.c.obj +[229/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_handlers.c.obj +[230/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-ccm.c.obj +[231/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/tls_mbedtls.c.obj +[232/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj +[233/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/err.c.obj +[234/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-ec.c.obj +[235/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip_defaults.c.obj +[236/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj +[237/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/if_api.c.obj +[238/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_sntp.c.obj +[239/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/sntp/sntp.c.obj +[240/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj +[241/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj +[242/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netifapi.c.obj +[243/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netdb.c.obj +[244/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj +[245/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj +[246/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/sntp/sntp.c.obj +[247/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/init.c.obj +[248/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/def.c.obj +[249/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ip.c.obj +[250/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/netbiosns/netbiosns.c.obj +[251/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj +[252/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/mem.c.obj +[253/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/memp.c.obj +[254/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/sys.c.obj +[255/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj +[256/1343] Linking C static library esp-idf/wpa_supplicant/libwpa_supplicant.a +[257/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/stats.c.obj +[258/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/timeouts.c.obj +[259/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/autoip.c.obj +[260/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/dns.c.obj +[261/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/raw.c.obj +[262/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/icmp.c.obj +[263/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/igmp.c.obj +[264/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj +[265/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj +[266/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj +[267/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/netif.c.obj +[268/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj +[269/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj +[270/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_frag.c.obj +[271/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/dhcp6.c.obj +[272/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/dhcp.c.obj +[273/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ethip6.c.obj +[274/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/inet6.c.obj +[275/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/icmp6.c.obj +[276/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif.c.obj +[277/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj +[278/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_frag.c.obj +[279/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_addr.c.obj +[280/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj +[281/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif_fdb.c.obj +[282/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_out.c.obj +[283/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_in.c.obj +[284/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_napt.c.obj +[285/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/mld6.c.obj +[286/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/auth.c.obj +[287/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp.c.obj +[288/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ccp.c.obj +[289/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-new.c.obj +[290/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/slipif.c.obj +[291/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-md5.c.obj +[292/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/demand.c.obj +[293/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap_ms.c.obj +[294/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6.c.obj +[295/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eap.c.obj +[296/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eui64.c.obj +[297/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ecp.c.obj +[298/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj +[299/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/fsm.c.obj +[300/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipv6cp.c.obj +[301/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppcrypt.c.obj +[302/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipcp.c.obj +[303/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/magic.c.obj +[304/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/lcp.c.obj +[305/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ppp.c.obj +[306/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/multilink.c.obj +[307/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppapi.c.obj +[308/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/mppe.c.obj +[309/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppol2tp.c.obj +[310/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppos.c.obj +[311/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppoe.c.obj +[312/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/upap.c.obj +[313/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/utils.c.obj +[314/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/vj.c.obj +[315/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/tcp_isn_default.c.obj +[316/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/if_index.c.obj +[317/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/arc4.c.obj +[318/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/des.c.obj +[319/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/esp_ping.c.obj +[320/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md4.c.obj +[321/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md5.c.obj +[322/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping.c.obj +[323/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/sockets_ext.c.obj +[324/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/sha1.c.obj +[325/1343] Linking C static library esp-idf/esp_netif/libesp_netif.a +[326/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/acd_dhcp_check.c.obj +[327/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32xx/vfs_lwip.c.obj +[328/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/lwip_default_hooks.c.obj +[329/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/freertos/sys_arch.c.obj +[330/1343] Building C object esp-idf/esp_vfs_console/CMakeFiles/__idf_esp_vfs_console.dir/vfs_console.c.obj +[331/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/debug/lwip_debug.c.obj +[332/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_connection_monitor.c.obj +[333/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/nullfs.c.obj +[334/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/lib_printf.c.obj +[335/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_eventfd.c.obj +[336/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/dhcpserver/dhcpserver.c.obj +[337/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj +[338/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_common.c.obj +[339/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/esp32s3/phy_init_data.c.obj +[340/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping_sock.c.obj +[341/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag.c.obj +[342/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/btbb_init.c.obj +[343/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/nd6.c.obj +[344/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_semihost.c.obj +[345/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_vfs.c.obj +[346/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj +[347/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs.c.obj +[348/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_platform.cpp.obj +[349/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_aes.c.obj +[350/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader.c.obj +[351/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_xts_aes.c.obj +[352/1343] Linking C static library esp-idf/lwip/liblwip.a +[353/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition.cpp.obj +[354/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/default_event_loop.c.obj +[355/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_lookup.cpp.obj +[356/1343] Linking C static library esp-idf/vfs/libvfs.a +[357/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event_private.c.obj +[358/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_wakeup.c.obj +[359/1343] Linking C static library esp-idf/esp_vfs_console/libesp_vfs_console.a +[360/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event.c.obj +[361/1343] Linking C static library esp-idf/esp_driver_usb_serial_jtag/libesp_driver_usb_serial_jtag.a +[362/1343] Linking C static library esp-idf/esp_phy/libesp_phy.a +[363/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uhci.c.obj +[364/1343] Building C object esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj +[365/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_vfs.c.obj +[366/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer_common.c.obj +[367/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_init.c.obj +[368/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer.c.obj +[369/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj +[370/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj +[371/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj +[372/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj +[373/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj +[374/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_exception_stubs.cpp.obj +[375/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_init.cpp.obj +[376/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart.c.obj +[377/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_cond_var.c.obj +[378/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_local_storage.c.obj +[379/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj +[380/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_rwlock.c.obj +[381/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_guards.cpp.obj +[382/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/abort.c.obj +[383/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/init.c.obj +[384/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_semaphore.c.obj +[385/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/assert.c.obj +[386/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/poll.c.obj +[387/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/heap.c.obj +[388/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/pthread.c.obj +[389/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/locks.c.obj +[390/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/getentropy.c.obj +[391/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/random.c.obj +[392/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/termios.c.obj +[393/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/sysconf.c.obj +[394/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/scandir.c.obj +[395/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/realpath.c.obj +[396/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/time.c.obj +[397/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/syscalls.c.obj +[398/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/esp_time_impl.c.obj +[399/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_syscalls.c.obj +[400/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/flockfile.c.obj +[401/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_init.c.obj +[402/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/xtensa/stdatomic_s32c1i.c.obj +[403/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/newlib_init.c.obj +[404/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/stdatomic.c.obj +[405/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj +[406/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj +[407/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/app_startup.c.obj +[408/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj +[409/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj +[410/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/timers.c.obj +[411/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj +[412/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/event_groups.c.obj +[413/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/stream_buffer.c.obj +[414/1343] Building ASM object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/portasm.S.obj +[415/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_init.c.obj +[416/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_overlay_os_hook.c.obj +[417/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/port.c.obj +[418/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/freertos_compatibility.c.obj +[419/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions_event_groups.c.obj +[420/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[421/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[422/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions.c.obj +[423/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[424/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[425/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_item_hash_list.cpp.obj +[426/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj +[427/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj +[428/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj +[429/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_ctrl_os.c.obj +[430/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_cxx_api.cpp.obj +[431/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mac_addr.c.obj +[432/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/revision.c.obj +[433/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_locked.cpp.obj +[434/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_gpio_reserve.c.obj +[435/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj +[436/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj +[437/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj +[438/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_clk_tree.c.obj +[439/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj +[440/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sar_periph_ctrl_common.c.obj +[441/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/io_mux.c.obj +[442/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_encrypted_partition.cpp.obj +[443/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_simple.cpp.obj +[444/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_types.cpp.obj +[445/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_dma_utils.c.obj +[446/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_clk_tree_common.c.obj +[447/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma_link.c.obj +[448/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modem.c.obj +[449/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_utils.c.obj +[450/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_mspi.c.obj +[451/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_pagemanager.cpp.obj +[452/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_usb.c.obj +[453/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_share_hw_ctrl.c.obj +[454/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/adc_share_hw_ctrl.c.obj +[455/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_console.c.obj +[456/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_manager.cpp.obj +[457/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_bus_lock.c.obj +[458/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_event.c.obj +[459/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_async_memcpy.c.obj +[460/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/systimer.c.obj +[461/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_gpio.c.obj +[462/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/deprecated/gdma_legacy.c.obj +[463/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_wake_stub.c.obj +[464/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/mspi_timing_tuning.c.obj +[465/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_page.cpp.obj +[466/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[467/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/async_memcpy_gdma.c.obj +[468/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[469/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[470/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/power_supply/brownout.c.obj +[471/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[472/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_memprot_conv.c.obj +[473/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[474/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_config.c.obj +[475/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[476/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_lock.c.obj +[477/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clock_output.c.obj +[478/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/sar_periph_ctrl.c.obj +[479/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/init.c.obj +[480/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[481/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma.c.obj +[482/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c.obj +[483/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[484/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_hmac.c.obj +[485/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_periph_clk.c.obj +[486/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[487/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_ds.c.obj +[488/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[489/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[490/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[491/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/lowpower/port/esp32s3/sleep_cpu.c.obj +[492/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[493/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[494/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[495/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[496/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[497/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[498/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[499/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[500/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[501/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[502/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[503/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[504/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[505/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[506/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[507/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj +[508/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[509/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[510/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[511/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[512/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[513/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[514/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[515/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_storage.cpp.obj +[516/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/esp32s3/memory_layout.c.obj +[517/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[518/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/memory_layout_utils.c.obj +[519/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_lock.c.obj +[520/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[521/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj +[522/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_timestamp.c.obj +[523/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/util.c.obj +[524/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[525/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj +[526/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_init.c.obj +[527/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[528/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[529/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_api.cpp.obj +[530/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_write.c.obj +[531/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj +[532/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/log_level.c.obj +[533/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[534/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[535/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[536/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/tag_log_level.c.obj +[537/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/cache/log_binary_heap.c.obj +[538/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/linked_list/log_linked_list.c.obj +[539/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[540/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[541/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/color_hal.c.obj +[542/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_memprot.c.obj +[543/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[544/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[545/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_encrypt_hal_iram.c.obj +[546/1343] Linking C static library esp-idf/nvs_flash/libnvs_flash.a +[547/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal.c.obj +[548/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/clk_tree_hal.c.obj +[549/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gpio_hal.c.obj +[550/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj +[551/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rtc_io_hal.c.obj +[552/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal_iram.c.obj +[553/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/timer_hal.c.obj +[554/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal.c.obj +[555/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal_iram.c.obj +[556/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal.c.obj +[557/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal_iram.c.obj +[558/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rmt_hal.c.obj +[559/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal.c.obj +[560/1343] Linking C static library esp-idf/esp_event/libesp_event.a +[561/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj +[562/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/pcnt_hal.c.obj +[563/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mcpwm_hal.c.obj +[564/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uhci_hal.c.obj +[565/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdm_hal.c.obj +[566/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdmmc_hal.c.obj +[567/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_top.c.obj +[568/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/lcd_hal.c.obj +[569/1343] Linking C static library esp-idf/esp_driver_uart/libesp_driver_uart.a +[570/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpi_hal.c.obj +[571/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal_common.c.obj +[572/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sha_hal.c.obj +[573/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_oneshot_hal.c.obj +[574/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_ahb_v1.c.obj +[575/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj +[576/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2s_hal.c.obj +[577/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal.c.obj +[578/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/aes_hal.c.obj +[579/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal.c.obj +[580/1343] Linking C static library esp-idf/esp_ringbuf/libesp_ringbuf.a +[581/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ds_hal.c.obj +[582/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal.c.obj +[583/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal_iram.c.obj +[584/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hmac_hal.c.obj +[585/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_serial_jtag_hal.c.obj +[586/1343] Linking C static library esp-idf/esp_driver_gptimer/libesp_driver_gptimer.a +[587/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_wrap_hal.c.obj +[588/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/twai_hal_v1.c.obj +[589/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cam_hal.c.obj +[590/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sensor_hal.c.obj +[591/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj +[592/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/touch_sensor_hal.c.obj +[593/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/xt_wdt_hal.c.obj +[594/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[595/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sens_hal.c.obj +[596/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[597/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/rtc_cntl_hal.c.obj +[598/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/tlsf/tlsf.c.obj +[599/1343] Linking C static library esp-idf/esp_timer/libesp_timer.a +[600/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[601/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[602/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[603/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hd_hal.c.obj +[604/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[605/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[606/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[607/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[608/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[609/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal_iram.c.obj +[610/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[611/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[612/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_dwc_hal.c.obj +[613/1343] Linking C static library esp-idf/cxx/libcxx.a +[614/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system_console.c.obj +[615/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[616/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/stack_check.c.obj +[617/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj +[618/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj +[619/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_ipc.c.obj +[620/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/system_time.c.obj +[621/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj +[622/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup.c.obj +[623/1343] Linking C static library esp-idf/pthread/libpthread.a +[624/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj +[625/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/xt_wdt.c.obj +[626/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj +[627/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/panic.c.obj +[628/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup_funcs.c.obj +[629/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_routines.S.obj +[630/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_handler.S.obj +[631/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_port.c.obj +[632/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_ipc_isr.c.obj +[633/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/image_process.c.obj +[634/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj +[635/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj +[636/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_handler_asm.S.obj +[637/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack_asm.S.obj +[638/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers_asm.S.obj +[639/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_arch.c.obj +[640/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj +[641/1343] Linking C static library esp-idf/newlib/libnewlib.a +[642/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_stubs.c.obj +[643/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack.c.obj +[644/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/highint_hdl.S.obj +[645/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj +[646/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/trax.c.obj +[647/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/reset_reason.c.obj +[648/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/apb_backup_dma.c.obj +[649/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers.c.obj +[650/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp32s3/spi_flash_oct_flash_init.c.obj +[651/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_drivers.c.obj +[652/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_hpm_enable.c.obj +[653/1343] Linking C static library esp-idf/freertos/libfreertos.a +[654/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_issi.c.obj +[655/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/cache_err_int.c.obj +[656/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj +[657/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/system_internal.c.obj +[658/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj +[659/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_boya.c.obj +[660/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_gd.c.obj +[661/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_th.c.obj +[662/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_winbond.c.obj +[663/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic.c.obj +[664/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/clk.c.obj +[665/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic_opi.c.obj +[666/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_generic.c.obj +[667/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/memspi_host_driver.c.obj +[668/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[669/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/port/esp32s3/ext_mem_layout.c.obj +[670/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj +[671/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj +[672/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj +[673/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj +[674/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/heap_align_hw.c.obj +[675/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_utils.c.obj +[676/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj +[677/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[678/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[679/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[680/1343] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[681/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[682/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_msync.c.obj +[683/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[684/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[685/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[686/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[687/1343] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[688/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_spi_init.c.obj +[689/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[690/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[691/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj +[692/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[693/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[694/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/secure_boot_secure_features.c.obj +[695/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[696/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[697/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[698/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[699/1343] Linking C static library esp-idf/esp_security/libesp_security.a +[700/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[701/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[702/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[703/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_api.c.obj +[704/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[705/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[706/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[707/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[708/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_startup.c.obj +[709/1343] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[710/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_app_desc.c.obj +[711/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/debug.c.obj +[712/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_reader.c.obj +[713/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition_target.c.obj +[714/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[715/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_trace.c.obj +[716/1343] Linking C static library esp-idf/soc/libsoc.a +[717/1343] Building C object esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj +[718/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition.c.obj +[719/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_keys.c.obj +[720/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_server.c.obj +[721/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_client.c.obj +[722/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cache.c.obj +[723/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_debug_helpers_generated.c.obj +[724/1343] Linking C static library esp-idf/heap/libheap.a +[725/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cookie.c.obj +[726/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_client.c.obj +[727/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_generic.c.obj +[728/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ciphersuites.c.obj +[729/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ticket.c.obj +[730/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_platform_time.c.obj +[731/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/mbedtls_debug.c.obj +[732/1343] Linking C static library esp-idf/log/liblog.a +[733/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_ops.c.obj +[734/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_client.c.obj +[735/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write.c.obj +[736/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_create.c.obj +[737/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesni.c.obj +[738/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_crt.c.obj +[739/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesce.c.obj +[740/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_csr.c.obj +[741/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/pkcs7.c.obj +[742/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crl.c.obj +[743/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_csr.c.obj +[744/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aes.c.obj +[745/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/net_sockets.c.obj +[746/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod.c.obj +[747/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aria.c.obj +[748/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1parse.c.obj +[749/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod_raw.c.obj +[750/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/base64.c.obj +[751/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_msg.c.obj +[752/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_server.c.obj +[753/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/block_cipher.c.obj +[754/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1write.c.obj +[755/1343] Linking C static library esp-idf/hal/libhal.a +[756/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/camellia.c.obj +[757/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chacha20.c.obj +[758/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509.c.obj +[759/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chachapoly.c.obj +[760/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_core.c.obj +[761/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ccm.c.obj +[762/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/des.c.obj +[763/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/constant_time.c.obj +[764/1343] Linking C static library esp-idf/esp_rom/libesp_rom.a +[765/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/dhm.c.obj +[766/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdh.c.obj +[767/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher_wrap.c.obj +[768/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecjpake.c.obj +[769/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cmac.c.obj +[770/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ctr_drbg.c.obj +[771/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves_new.c.obj +[772/1343] Linking C static library esp-idf/esp_common/libesp_common.a +[773/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdsa.c.obj +[774/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy_poll.c.obj +[775/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls.c.obj +[776/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hkdf.c.obj +[777/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy.c.obj +[778/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hmac_drbg.c.obj +[779/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/memory_buffer_alloc.c.obj +[780/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/error.c.obj +[781/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher.c.obj +[782/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/nist_kw.c.obj +[783/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md5.c.obj +[784/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lmots.c.obj +[785/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crt.c.obj +[786/1343] Linking C static library esp-idf/esp_system/libesp_system.a +[787/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum.c.obj +[788/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/padlock.c.obj +[789/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp.c.obj +[790/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_ecc.c.obj +[791/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pem.c.obj +[792/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs12.c.obj +[793/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/gcm.c.obj +[794/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md.c.obj +[795/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lms.c.obj +[796/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/oid.c.obj +[797/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs5.c.obj +[798/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform_util.c.obj +[799/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/poly1305.c.obj +[800/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves.c.obj +[801/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform.c.obj +[802/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_wrap.c.obj +[803/1343] Linking C static library esp-idf/spi_flash/libspi_flash.a +[804/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk.c.obj +[805/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkwrite.c.obj +[806/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_aead.c.obj +[807/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_client.c.obj +[808/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_driver_wrappers_no_static.c.obj +[809/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_cipher.c.obj +[810/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_pake.c.obj +[811/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_se.c.obj +[812/1343] Linking C static library esp-idf/esp_mm/libesp_mm.a +[813/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkparse.c.obj +[814/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_mac.c.obj +[815/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ffdh.c.obj +[816/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_hash.c.obj +[817/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_rsa.c.obj +[818/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ecp.c.obj +[819/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_its_file.c.obj +[820/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ripemd160.c.obj +[821/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_storage.c.obj +[822/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha3.c.obj +[823/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/threading.c.obj +[824/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha1.c.obj +[825/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa_alt_helpers.c.obj +[826/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/timing.c.obj +[827/1343] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[828/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha512.c.obj +[829/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version.c.obj +[830/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_util.c.obj +[831/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version_features.c.obj +[832/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_slot_management.c.obj +[833/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_gdma_impl.c.obj +[834/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha_gdma_impl.c.obj +[835/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha256.c.obj +[836/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hardware.c.obj +[837/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_mem.c.obj +[838/1343] Linking C static library esp-idf/efuse/libefuse.a +[839/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_timing.c.obj +[840/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_xts.c.obj +[841/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c.obj +[842/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_common.c.obj +[843/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/esp_sha.c.obj +[844/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hmac_pbkdf2.c.obj +[845/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c.obj +[846/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_dma_core.c.obj +[847/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_ds_common.c.obj +[848/1343] Linking C static library esp-idf/esp_partition/libesp_partition.a +[849/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/sha.c.obj +[850/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c.obj +[851/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_dec_alt.c.obj +[852/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/bignum_alt.c.obj +[853/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/esp_bignum.c.obj +[854/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha256.c.obj +[855/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha1.c.obj +[856/1343] Creating directories for 'bootloader' +[857/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/md/esp_md.c.obj +[858/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha512.c.obj +[859/1343] Linking C static library esp-idf/app_update/libapp_update.a +[860/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/x25519.c.obj +[861/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_gcm.c.obj +[862/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/Hacl_Curve25519_joined.c.obj +[863/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m_driver_entrypoints.c.obj +[864/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m/p256-m.c.obj +[865/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/everest.c.obj +[866/1343] No download step for 'bootloader' +[867/1343] No update step for 'bootloader' +[868/1343] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[869/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa.c.obj +[870/1343] No patch step for 'bootloader' +[871/1343] Linking C static library esp-idf/esp_app_format/libesp_app_format.a +[872/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedtls.a +[873/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedx509.a +[874/1343] Minifying + gzipping web resources +Minifying web resources in /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui/web_optimized... + JS js/terminal.js: 31,108 -> 20,066 (35.5% saved) + JS js/router.js: 6,414 -> 3,839 (40.1% saved) + JS js/dragSort.js: 11,460 -> 7,603 (33.7% saved) + JS js/api.js: 36,638 -> 24,339 (33.6% saved) + JS js/i18n.js: 7,208 -> 4,320 (40.1% saved) + JS js/app.js: 1,129,944 -> 840,829 (25.6% saved) + JS js/lang/en-US.js: 178,439 -> 143,161 (19.8% saved) + JS js/lang/zh-CN.js: 172,046 -> 137,314 (20.2% saved) + CSS css/style.css: 179,071 -> 129,275 (27.8% saved) + CSS fonts/remixicon.css: 5,940 -> 4,860 (18.2% saved) + + Total saved: 442,662 bytes (432.3 KB) + +Gzipping web resources in /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui/web_optimized... + GZ js/terminal.js: 20,066 -> 5,565 (72.3% smaller) + GZ js/router.js: 3,839 -> 1,340 (65.1% smaller) + GZ js/dragSort.js: 7,603 -> 1,869 (75.4% smaller) + GZ js/api.js: 24,339 -> 6,163 (74.7% smaller) + GZ js/i18n.js: 4,320 -> 1,460 (66.2% smaller) + GZ js/app.js: 840,829 -> 167,747 (80.0% smaller) + GZ js/lang/en-US.js: 143,161 -> 43,017 (70.0% smaller) + GZ js/lang/zh-CN.js: 137,314 -> 45,286 (67.0% smaller) + GZ vendor/xterm/fit.min.js: 1,789 -> 822 (54.1% smaller) + GZ vendor/xterm/xterm.min.js: 283,670 -> 65,684 (76.8% smaller) + GZ css/style.css: 129,275 -> 20,658 (84.0% smaller) + GZ fonts/remixicon.css: 4,860 -> 1,263 (74.0% smaller) + GZ vendor/xterm/xterm.css: 5,383 -> 2,037 (62.2% smaller) + GZ index.html: 26,676 -> 7,261 (72.8% smaller) + + Gzipped 14 files: 1,633,124 -> 370,172 (77.3% overall) +Done. +[875/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto.c.obj +[876/1343] cd /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ssh-stack-candidate/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[877/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a +[878/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/p256-m/libp256m.a +[879/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/everest/libeverest.a +[880/1343] Generating x509_crt_bundle +[881/1343] Generating ../../x509_crt_bundle.S +[882/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_context.S.obj +[883/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr_asm.S.obj +[884/1343] Building ASM object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/__/__/x509_crt_bundle.S.obj +[885/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[886/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[887/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_trace.c.obj +[888/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr.c.obj +[889/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_glitch_filter_ops.c.obj +[890/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_pin_glitch_filter.c.obj +[891/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj +[892/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_vectors.S.obj +[893/1343] Building C object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/esp_crt_bundle/esp_crt_bundle.c.obj +[894/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/crc32.cpp.obj +[895/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/dedic_gpio.c.obj +[896/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj +[897/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Perf.cpp.obj +[898/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/SPI_Flash.cpp.obj +[899/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio.c.obj +[900/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/rtc_io.c.obj +[901/1343] Linking C static library esp-idf/mbedtls/libmbedtls.a +[902/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/Partition.cpp.obj +[903/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_wl.c.obj +[904/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_rawflash.c.obj +[905/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Safe.cpp.obj +[906/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ffunicode.c.obj +[907/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/port/freertos/ffsystem.c.obj +[908/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_sdmmc.c.obj +[909/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/wear_levelling.cpp.obj +[910/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio.c.obj +[911/1343] Linking C static library esp-idf/esp_pm/libesp_pm.a +[912/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_cache.c.obj +[913/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_spiflash.c.obj +[914/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_sdmmc.c.obj +[915/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs_api.c.obj +[916/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_gc.c.obj +[917/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_common.c.obj +[918/1343] Linking C static library esp-idf/esp_driver_gpio/libesp_driver_gpio.a +[919/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_hydrogen.c.obj +[920/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/commands.c.obj +[921/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/split_argv.c.obj +[922/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Flash.cpp.obj +[923/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_cmd.c.obj +[924/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat.c.obj +[925/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dbl.c.obj +[926/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_chip.c.obj +[927/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_check.c.obj +[928/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/esp_spiffs.c.obj +[929/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/linenoise/linenoise.c.obj +[930/1343] Linking C static library esp-idf/xtensa/libxtensa.a +[931/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_internal.c.obj +[932/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_file.c.obj +[933/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dstr.c.obj +[934/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_end.c.obj +[935/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_int.c.obj +[936/1343] Linking C static library esp-idf/wear_levelling/libwear_levelling.a +[937/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rem.c.obj +[938/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_hashtable.c.obj +[939/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rex.c.obj +[940/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_date.c.obj +[941/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_lit.c.obj +[942/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_nucleus.c.obj +[943/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_str.c.obj +[944/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/argtable3.c.obj +[945/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth_netif_glue.c.obj +[946/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/compress.c.obj +[947/1343] Linking C static library esp-idf/spiffs/libspiffs.a +[948/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_utils.c.obj +[949/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/adler32.c.obj +[950/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth.c.obj +[951/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/crc32.c.obj +[952/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ff.c.obj +[953/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzclose.c.obj +[954/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/phy/esp_eth_phy_802_3.c.obj +[955/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inffast.c.obj +[956/1343] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON_Utils.c.obj +[957/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzwrite.c.obj +[958/1343] Linking C static library esp-idf/fatfs/libfatfs.a +[959/1343] Building C object esp-idf/ts_event/CMakeFiles/__idf_ts_event.dir/src/ts_event.c.obj +[960/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzlib.c.obj +[961/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inftrees.c.obj +[962/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_phy_w5500.c.obj +[963/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/uncompr.c.obj +[964/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/zutil.c.obj +[965/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzread.c.obj +[966/1343] Linking C static library esp-idf/ts_event/libts_event.a +[967/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/infback.c.obj +[968/1343] Linking C static library esp-idf/console/libconsole.a +[969/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_encoder.c.obj +[970/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_mac_w5500.c.obj +[971/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/trees.c.obj +[972/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_dev.c.obj +[973/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/example.c.obj +[974/1343] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON.c.obj +[975/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/deflate.c.obj +[976/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_api.c.obj +[977/1343] Building C object esp-idf/esp_https_server/CMakeFiles/__idf_esp_https_server.dir/src/https_server.c.obj +[978/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inflate.c.obj +[979/1343] Building C object esp-idf/ts_log/CMakeFiles/__idf_ts_log.dir/src/ts_log.c.obj +[980/1343] Building C object esp-idf/espressif__esp_jpeg/CMakeFiles/__idf_espressif__esp_jpeg.dir/jpeg_decoder.c.obj +[981/1343] Linking C static library esp-idf/json/libjson.a +[982/1343] Linking C static library esp-idf/esp_eth/libesp_eth.a +[983/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_spi_dev.c.obj +[984/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngmem.c.obj +[985/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrio.c.obj +[986/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngpread.c.obj +[987/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngerror.c.obj +[988/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtrans.c.obj +[989/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwio.c.obj +[990/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngget.c.obj +[991/1343] Linking C static library esp-idf/espressif__zlib/libespressif__zlib.a +[992/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwtran.c.obj +[993/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngset.c.obj +[994/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/png.c.obj +[995/1343] Building C object esp-idf/espressif__esp_websocket_client/CMakeFiles/__idf_espressif__esp_websocket_client.dir/esp_websocket_client.c.obj +[996/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_mem_caps.c.obj +[997/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtest.c.obj +[998/1343] Building C object esp-idf/ts_jsonpath/CMakeFiles/__idf_ts_jsonpath.dir/src/ts_jsonpath.c.obj +[999/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwrite.c.obj +[1000/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_networking_lwip.c.obj +[1001/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/blowfish.c.obj +[1002/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngread.c.obj +[1003/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent_win.c.obj +[1004/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/bcrypt_pbkdf.c.obj +[1005/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwutil.c.obj +[1006/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrutil.c.obj +[1007/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent.c.obj +[1008/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/global.c.obj +[1009/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/hostkey.c.obj +[1010/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_console.c.obj +[1011/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/comp.c.obj +[1012/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/crypt.c.obj +[1013/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/keepalive.c.obj +[1014/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrtran.c.obj +[1015/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/libgcrypt.c.obj +[1016/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/openssl.c.obj +[1017/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mac.c.obj +[1018/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mbedtls.c.obj +[1019/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/channel.c.obj +[1020/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/misc.c.obj +[1021/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/os400qc3.c.obj +[1022/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/knownhost.c.obj +[1023/1343] Linking C static library esp-idf/ts_log/libts_log.a +[1024/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/scp.c.obj +[1025/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/pem.c.obj +[1026/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth_kbd_packet.c.obj +[1027/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/wincng.c.obj +[1028/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/version.c.obj +[1029/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/packet.c.obj +[1030/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/transport.c.obj +[1031/1343] Linking C static library esp-idf/espressif__esp_websocket_client/libespressif__esp_websocket_client.a +[1032/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/publickey.c.obj +[1033/1343] Building C object esp-idf/ts_service/CMakeFiles/__idf_ts_service.dir/src/ts_service.c.obj +[1034/1343] Linking C static library esp-idf/esp_https_server/libesp_https_server.a +[1035/1343] Linking C static library esp-idf/espressif__led_strip/libespressif__led_strip.a +[1036/1343] Building C object esp-idf/ts_mempool/CMakeFiles/__idf_ts_mempool.dir/src/ts_mempool.c.obj +[1037/1343] Linking C static library esp-idf/espressif__esp_jpeg/libespressif__esp_jpeg.a +[1038/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/session.c.obj +[1039/1343] Linking C static library esp-idf/ts_jsonpath/libts_jsonpath.a +[1040/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_meta.c.obj +[1041/1343] Linking C static library esp-idf/espressif__libpng/libespressif__libpng.a +[1042/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_json.c.obj +[1043/1343] Linking C static library esp-idf/ts_mempool/libts_mempool.a +[1044/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth.c.obj +[1045/1343] Linking C static library esp-idf/ts_service/libts_service.a +[1046/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_nvs.c.obj +[1047/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_schemas.c.obj +[1048/1343] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert_time.c.obj +[1049/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/kex.c.obj +[1050/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_file.c.obj +[1051/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config.c.obj +[1052/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/sftp.c.obj +[1053/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_security.c.obj +[1054/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_auth.c.obj +[1055/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_module.c.obj +[1056/1343] Building C object esp-idf/ts_config_pack/CMakeFiles/__idf_ts_config_pack.dir/src/ts_config_pack.c.obj +[1057/1343] Linking C static library esp-idf/ch405labs_esp_libssh2/libch405labs_esp_libssh2.a +[1058/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_known_hosts.c.obj +[1059/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_log_watch.c.obj +[1060/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_shell.c.obj +[1061/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_crypto.c.obj +[1062/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_probe.c.obj +[1063/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_client.c.obj +[1064/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_scp.c.obj +[1065/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_keystore.c.obj +[1066/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_port_forward.c.obj +[1067/1343] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert.c.obj +[1068/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_sftp.c.obj +[1069/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_hosts_config.c.obj +[1070/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns.c.obj +[1071/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_automation.c.obj +[1072/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_store.c.obj +[1073/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_variable.c.obj +[1074/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_compat.c.obj +[1075/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_commands_config.c.obj +[1076/1343] Linking C static library esp-idf/espressif__mdns/libespressif__mdns.a +[1077/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_codec.c.obj +[1078/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_freertos.c.obj +[1079/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_cache.c.obj +[1080/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_memory.c.obj +[1081/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_port_esp32.c.obj +[1082/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity/src/unity.c.obj +[1083/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/constants.pb-c.c.obj +[1084/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_runner.c.obj +[1085/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/port/esp/unity_utils_memory_esp.c.obj +[1086/1343] Linking C static library esp-idf/ts_config/libts_config.a +[1087/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec0.pb-c.c.obj +[1088/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/common/protocomm.c.obj +[1089/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_service.c.obj +[1090/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/session.pb-c.c.obj +[1091/1343] Linking C static library esp-idf/ts_config_pack/libts_config_pack.a +[1092/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec1.pb-c.c.obj +[1093/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_console.c.obj +[1094/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security0.c.obj +[1095/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec2.pb-c.c.obj +[1096/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security1.c.obj +[1097/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_httpd.c.obj +[1098/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp.c.obj +[1099/1343] Linking C static library esp-idf/ts_cert/libts_cert.a +[1100/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace.c.obj +[1101/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp_mpi.c.obj +[1102/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security2.c.obj +[1103/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/host_file_io.c.obj +[1104/1343] Building C object esp-idf/cmock/CMakeFiles/__idf_cmock.dir/CMock/src/cmock.c.obj +[1105/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace_util.c.obj +[1106/1343] Linking C static library esp-idf/unity/libunity.a +[1107/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/port/port_uart.c.obj +[1108/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp_share_ctrl.c.obj +[1109/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/esp_cam_ctlr.c.obj +[1110/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_gdma.c.obj +[1111/1343] Building C object esp-idf/protobuf-c/CMakeFiles/__idf_protobuf-c.dir/protobuf-c/protobuf-c/protobuf-c.c.obj +[1112/1343] Linking C static library esp-idf/ts_security/libts_security.a +[1113/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidd.c.obj +[1114/1343] Linking C static library esp-idf/protobuf-c/libprotobuf-c.a +[1115/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_common.c.obj +[1116/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hid_common.c.obj +[1117/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_io.c.obj +[1118/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_engine.c.obj +[1119/1343] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/common/touch_sens_common.c.obj +[1120/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ssd1306.c.obj +[1121/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ops.c.obj +[1122/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_st7789.c.obj +[1123/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidh.c.obj +[1124/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_source_manager.c.obj +[1125/1343] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/hw_ver2/touch_version_specific.c.obj +[1126/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_cam.c.obj +[1127/1343] Linking C static library esp-idf/protocomm/libprotocomm.a +[1128/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_init.c.obj +[1129/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v1.c.obj +[1130/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/proto-c/esp_local_ctrl.pb-c.c.obj +[1131/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_action_manager.c.obj +[1132/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/spi/esp_lcd_panel_io_spi.c.obj +[1133/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl.c.obj +[1134/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_handler.c.obj +[1135/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_nt35510.c.obj +[1136/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v2.c.obj +[1137/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_transport_httpd.c.obj +[1138/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_common.c.obj +[1139/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_sha.c.obj +[1140/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_crc.c.obj +[1141/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_flash.c.obj +[1142/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_uart.c.obj +[1143/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_binary.c.obj +[1144/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/port/xtensa/core_dump_port.c.obj +[1145/1343] Linking C static library esp-idf/ts_automation/libts_automation.a +[1146/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_elf.c.obj +[1147/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_access.c.obj +[1148/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_masks.c.obj +[1149/1343] Generating ../../lpmu-agx-network-setup.tar.gz.S +[1150/1343] Building C object esp-idf/nvs_sec_provider/CMakeFiles/__idf_nvs_sec_provider.dir/nvs_sec_provider.c.obj +[1151/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/platform_esp32_idf.c.obj +[1152/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_apis.c.obj +[1153/1343] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_utils.c.obj +[1154/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i80/esp_lcd_panel_io_i80.c.obj +[1155/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_button.c.obj +[1156/1343] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_mqueue.c.obj +[1157/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_outbox.c.obj +[1158/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_slider.c.obj +[1159/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config.c.obj +[1160/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_msg.c.obj +[1161/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_matrix.c.obj +[1162/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api.c.obj +[1163/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_network.c.obj +[1164/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_fan.c.obj +[1165/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_service.c.obj +[1166/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_system.c.obj +[1167/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_element.c.obj +[1168/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_power.c.obj +[1169/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/rgb/esp_lcd_panel_rgb.c.obj +[1170/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config_pack.c.obj +[1171/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_device.c.obj +[1172/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_monitor.c.obj +[1173/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_temp.c.obj +[1174/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_gpio.c.obj +[1175/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_dhcp.c.obj +[1176/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_nat.c.obj +[1177/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_storage.c.obj +[1178/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_hosts.c.obj +[1179/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_led.c.obj +[1180/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_time.c.obj +[1181/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_key.c.obj +[1182/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_sftp.c.obj +[1183/1343] Building ASM object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/__/__/lpmu-agx-network-setup.tar.gz.S.obj +[1184/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_wifi.c.obj +[1185/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_lpmu_access.c.obj +[1186/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_auth.c.obj +[1187/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ui.c.obj +[1188/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_log.c.obj +[1189/1343] Performing configure step for 'bootloader' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-ssh-stack-candidate/sdkconfig +-- Compiler supported targets: xtensa-esp-elf +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Bootloader project name: "bootloader" version: 1 +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.rom.ld +-- Components: bootloader bootloader_support efuse esp_app_format esp_bootloader_format esp_common esp_hw_support esp_rom esp_security esp_system esptool_py freertos hal log main micro-ecc newlib partition_table soc spi_flash xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/components/micro-ecc /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +-- Configuring done (6.7s) +-- Generating done (0.3s) +-- Build files have been written to: /tmp/tianshan-ssh-stack-candidate/build/bootloader +[1190/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_api.c.obj +[1191/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui.c.obj +[1192/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_cert.c.obj +[1193/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https.c.obj +[1194/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_operation.c.obj +[1195/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_i18n.c.obj +[1196/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console.c.obj +[1197/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/mqtt_client.c.obj +[1198/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_args.c.obj +[1199/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ota.c.obj +[1200/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_script.c.obj +[1201/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_auth.c.obj +[1202/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_api.c.obj +[1203/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_builtin.c.obj +[1204/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_monitor.c.obj +[1205/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[1206/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_device.c.obj +[1207/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fs.c.obj +[1208/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ssh.c.obj +[1209/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fan.c.obj +[1210/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_auto.c.obj +[1211/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_key.c.obj +[1212/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_nat.c.obj +[1213/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_hosts.c.obj +[1214/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_dhcp.c.obj +[1215/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_transport.c.obj +[1216/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_register.c.obj +[1217/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/linenoise/linenoise.c.obj +[1218/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_gpio.c.obj +[1219/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_config.c.obj +[1220/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ota.c.obj +[1221/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_power.c.obj +[1222/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_storage.c.obj +[1223/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_pki.c.obj +[1224/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_temp.c.obj +[1225/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_service.c.obj +[1226/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_net.c.obj +[1227/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_system.c.obj +[1228/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[1229/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_sftp.c.obj +[1230/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_voltprot.c.obj +[1231/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_version.c.obj +[1232/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota.c.obj +[1233/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_rollback.c.obj +[1234/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_wifi.c.obj +[1235/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ssh.c.obj +[1236/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_sdcard.c.obj +[1237/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net.c.obj +[1238/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_led.c.obj +[1239/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_recovery.c.obj +[1240/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_eth.c.obj +[1241/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net_manager.c.obj +[1242/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_wifi.c.obj +[1243/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_https.c.obj +[1244/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led.c.obj +[1245/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_nat.c.obj +[1246/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_time_sync.c.obj +[1247/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_https_server.c.obj +[1248/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_driver.c.obj +[1249/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_http_server.c.obj +[1250/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_layer.c.obj +[1251/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color.c.obj +[1252/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_download.c.obj +[1253/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_qrcode.c.obj +[1254/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_animation.c.obj +[1255/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_drivers.c.obj +[1256/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_font.c.obj +[1257/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_automation.c.obj +[1258/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_effect.c.obj +[1259/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_www.c.obj +[1260/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_text.c.obj +[1261/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color_correction.c.obj +[1262/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_usb_mux.c.obj +[1263/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_monitor.c.obj +[1264/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power.c.obj +[1265/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_preset.c.obj +[1266/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/qrcodegen/qrcodegen.c.obj +[1267/1343] Linking C static library esp-idf/ts_api/libts_api.a +[1268/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_dhcp_server.c.obj +[1269/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_hal.c.obj +[1270/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_i2c.c.obj +[1271/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_temp_source.c.obj +[1272/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_gpio.c.obj +[1273/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pwm.c.obj +[1274/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_device_ctrl.c.obj +[1275/1343] Linking C static library esp-idf/ts_https/libts_https.a +[1276/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pin_manager.c.obj +[1277/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_fan.c.obj +[1278/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/platform/esp32s3/ts_platform_s3.c.obj +[1279/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_compute_monitor.c.obj +[1280/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_spi.c.obj +[1281/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_adc.c.obj +[1282/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_image.c.obj +[1283/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_spiffs.c.obj +[1284/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_policy.c.obj +[1285/1343] Linking C static library esp-idf/ts_webui/libts_webui.a +[1286/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_helpers.c.obj +[1287/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage.c.obj +[1288/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_uart.c.obj +[1289/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_private.c.obj +[1290/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hub.c.obj +[1291/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_ctrl.c.obj +[1292/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/enum.c.obj +[1293/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_phy.c.obj +[1294/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_config.c.obj +[1295/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_scan.c.obj +[1296/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/handlers.c.obj +[1297/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_config.pb-c.c.obj +[1298/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_console.c.obj +[1299/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_scan.pb-c.c.obj +[1300/1343] Linking C static library esp-idf/ts_console/libts_console.a +[1301/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_constants.pb-c.c.obj +[1302/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_ctrl.pb-c.c.obj +[1303/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usbh.c.obj +[1304/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_sd.c.obj +[1305/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_host.c.obj +[1306/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_softap.c.obj +[1307/1343] Building C object esp-idf/ts_pki_client/CMakeFiles/__idf_ts_pki_client.dir/src/ts_pki_client.c.obj +[1308/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hcd_dwc.c.obj +[1309/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/main.c.obj +[1310/1343] Linking C static library esp-idf/cmock/libcmock.a +[1311/1343] Linking C static library esp-idf/app_trace/libapp_trace.a +[1312/1343] Linking C static library esp-idf/ts_ota/libts_ota.a +[1313/1343] Linking C static library esp-idf/esp_driver_cam/libesp_driver_cam.a +[1314/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_core_init.c.obj +[1315/1343] Linking C static library esp-idf/esp_driver_touch_sens/libesp_driver_touch_sens.a +[1316/1343] Linking C static library esp-idf/esp_hid/libesp_hid.a +[1317/1343] Linking C static library esp-idf/espcoredump/libespcoredump.a +[1318/1343] Linking C static library esp-idf/esp_local_ctrl/libesp_local_ctrl.a +[1319/1343] Linking C static library esp-idf/mqtt/libmqtt.a +[1320/1343] Linking C static library esp-idf/rt/librt.a +[1321/1343] Linking C static library esp-idf/perfmon/libperfmon.a +[1322/1343] Linking C static library esp-idf/esp_lcd/libesp_lcd.a +[1323/1343] Linking C static library esp-idf/nvs_sec_provider/libnvs_sec_provider.a +[1324/1343] Linking C static library esp-idf/touch_element/libtouch_element.a +[1325/1343] Linking C static library esp-idf/ts_net/libts_net.a +[1326/1343] Linking C static library esp-idf/usb/libusb.a +[1327/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_services.c.obj +[1328/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/manager.c.obj +[1329/1343] Linking C static library esp-idf/ts_led/libts_led.a +[1330/1343] Linking C static library esp-idf/wifi_provisioning/libwifi_provisioning.a +[1331/1343] Linking C static library esp-idf/ts_drivers/libts_drivers.a +[1332/1343] Linking C static library esp-idf/ts_hal/libts_hal.a +[1333/1343] Linking C static library esp-idf/ts_storage/libts_storage.a +[1334/1343] Linking C static library esp-idf/ts_pki_client/libts_pki_client.a +[1335/1343] Linking C static library esp-idf/main/libmain.a +[1336/1343] Performing build step for 'bootloader' +[1/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[2/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/util.c.obj +[3/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[4/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_timestamp.c.obj +[5/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_lock.c.obj +[6/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[7/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[8/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[9/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[10/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[11/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[12/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[13/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[14/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[15/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[16/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[17/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[18/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[19/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[20/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[21/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[22/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[23/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[24/123] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[25/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[26/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[27/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[28/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[29/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[30/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[31/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[32/123] Linking C static library esp-idf/log/liblog.a +[33/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[34/123] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[35/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[36/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[37/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[38/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[39/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[40/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[41/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[42/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[43/123] Linking C static library esp-idf/esp_rom/libesp_rom.a +[44/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[45/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[46/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[47/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[48/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[49/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[50/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[51/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[52/123] Linking C static library esp-idf/esp_common/libesp_common.a +[53/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[54/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[55/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_loader.c.obj +[56/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[57/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[58/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_soc.c.obj +[59/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console.c.obj +[60/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_init.c.obj +[61/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[62/123] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[63/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[64/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console_loader.c.obj +[65/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[66/123] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[67/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[68/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[69/123] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[70/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[71/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_esp32s3.c.obj +[72/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_panic.c.obj +[73/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[74/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[75/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[76/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[77/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[78/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[79/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[80/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[81/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[82/123] Linking C static library esp-idf/esp_system/libesp_system.a +[83/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[84/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[85/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[86/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[87/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[88/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[89/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[90/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[91/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[92/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[93/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[94/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[95/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[96/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[97/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[98/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[99/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[100/123] Generating project_elf_src_esp32s3.c +[101/123] Linking C static library esp-idf/efuse/libefuse.a +[102/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[103/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[104/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[105/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[106/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[107/123] Building C object CMakeFiles/bootloader.elf.dir/project_elf_src_esp32s3.c.obj +[108/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[109/123] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/bootloader_start.c.obj +[110/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[111/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[112/123] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[113/123] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[114/123] Linking C static library esp-idf/spi_flash/libspi_flash.a +[115/123] Linking C static library esp-idf/hal/libhal.a +[116/123] Building C object esp-idf/micro-ecc/CMakeFiles/__idf_micro-ecc.dir/uECC_verify_antifault.c.obj +[117/123] Linking C static library esp-idf/micro-ecc/libmicro-ecc.a +[118/123] Linking C static library esp-idf/soc/libsoc.a +[119/123] Linking C static library esp-idf/xtensa/libxtensa.a +[120/123] Linking C static library esp-idf/main/libmain.a +[121/123] Linking C executable bootloader.elf +[122/123] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-ssh-stack-candidate/build/bootloader/bootloader.bin +[123/123] cd /tmp/tianshan-ssh-stack-candidate/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ssh-stack-candidate/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[1337/1343] No install step for 'bootloader' +[1338/1343] Completed 'bootloader' +[1339/1343] Generating esp-idf/esp_system/ld/sections.ld +[1340/1343] Building C object CMakeFiles/TianShanOS.elf.dir/project_elf_src_esp32s3.c.obj +[1341/1343] Linking CXX executable TianShanOS.elf +[1342/1343] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-ssh-stack-candidate/build/TianShanOS.bin +[1343/1343] cd /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ssh-stack-candidate/build/partition_table/partition-table.bin /tmp/tianshan-ssh-stack-candidate/build/TianShanOS.bin +TianShanOS.bin binary size 0x215120 bytes. Smallest app partition is 0x300000 bytes. 0xeaee0 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-ssh-stack-candidate/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-ssh-stack-candidate/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-ssh-stack-candidate/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-ssh-stack-candidate/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-ssh-stack-candidate/build/www.bin +or from the "/private/tmp/tianshan-ssh-stack-candidate/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ssh-poll-stack/candidate/requests-en-US.json b/docs/repair/ssh-poll-stack/candidate/requests-en-US.json new file mode 100644 index 0000000..59325af --- /dev/null +++ b/docs/repair/ssh-poll-stack/candidate/requests-en-US.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/en-US.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/candidate/requests-zh-CN.json b/docs/repair/ssh-poll-stack/candidate/requests-zh-CN.json new file mode 100644 index 0000000..ef547b7 --- /dev/null +++ b/docs/repair/ssh-poll-stack/candidate/requests-zh-CN.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/candidate/sdkconfig-evidence.txt b/docs/repair/ssh-poll-stack/candidate/sdkconfig-evidence.txt new file mode 100644 index 0000000..3a04067 --- /dev/null +++ b/docs/repair/ssh-poll-stack/candidate/sdkconfig-evidence.txt @@ -0,0 +1,2875 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.5.2 Project Configuration +# +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_UHCI_SUPPORTED=y +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +CONFIG_SOC_CACHE_ACS_INVALID_STATE_ON_PANIC=y +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=5 +CONFIG_SOC_AHB_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=48 +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_SUPPORTS_PCM2PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_SUPPORTS_PDM2PCM=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_PCNT_GROUPS=1 +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1 +CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16 +CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1 +CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16 +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +CONFIG_SOC_SDM_GROUPS=1 +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_SPI_SCT_SUPPORTED=y +CONFIG_SOC_SPI_SCT_REG_NUM=14 +CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y +CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA +CONFIG_SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_TOUCH_SENSOR_VERSION=2 +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_MIN_CHAN_ID=1 +CONFIG_SOC_TOUCH_MAX_CHAN_ID=14 +CONFIG_SOC_TOUCH_SUPPORT_BENCHMARK=y +CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y +CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y +CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y +CONFIG_SOC_TOUCH_SUPPORT_DENOISE_CHAN=y +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_MASK_FILTER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE=y +CONFIG_SOC_UHCI_NUM=1 +CONFIG_SOC_USB_OTG_PERIPH_NUM=1 +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D2=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_CAM_PERIPH_NUM=1 +CONFIG_SOC_LCDCAM_CAM_DATA_WIDTH_MAX=16 +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_INIT_VERSION="5.5.2" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# + +# +# Bootloader manager +# +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + +# +# Application Rollback +# +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# end of Application Rollback + +# +# Recovery Bootloader and Rollback +# +# end of Recovery Bootloader and Rollback + +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# Log +# +CONFIG_BOOTLOADER_LOG_VERSION_1=y +CONFIG_BOOTLOADER_LOG_VERSION=1 +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format + +# +# Settings +# +CONFIG_BOOTLOADER_LOG_MODE_TEXT_EN=y +CONFIG_BOOTLOADER_LOG_MODE_TEXT=y +# end of Settings +# end of Log + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_OTG_NUM=3 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_SPI_FLASH_MMAP=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_HAS_VERSION=y +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y +CONFIG_ESP_ROM_CONSOLE_OUTPUT_SECONDARY=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="16MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_UART2 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set + +# +# Common Options +# + +# +# BLE Log +# +# CONFIG_BLE_LOG_ENABLED is not set +# end of BLE Log + +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set +# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set +# end of Common Options +# end of Bluetooth + +# +# Console Library +# +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library + +# +# Driver Configurations +# + +# +# Legacy TWAI Driver Configurations +# +# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of Legacy TWAI Driver Configurations + +# +# Legacy ADC Driver Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration + +# +# Legacy MCPWM Driver Configurations +# +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations + +# +# Legacy Timer Group Driver Configurations +# +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations + +# +# Legacy RMT Driver Configurations +# +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations + +# +# Legacy I2S Driver Configurations +# +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations + +# +# Legacy I2C Driver Configurations +# +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy PCNT Driver Configurations +# +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations + +# +# Legacy Temperature Sensor Driver Configurations +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Temperature Sensor Driver Configurations + +# +# Legacy Touch Sensor Driver Configurations +# +# CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Touch Sensor Driver Configurations +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration + +# +# Wireless Coexistence +# +CONFIG_ESP_COEX_ENABLED=y +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# end of Common ESP-related + +# +# ESP-Driver:Camera Controller Configurations +# +# CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE is not set +# end of ESP-Driver:Camera Controller Configurations + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_CACHE_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y +# CONFIG_MCPWM_ISR_CACHE_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +CONFIG_MCPWM_OBJ_CACHE_SAFE=y +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations + +# +# ESP-Driver:PCNT Configurations +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# ESP-Driver:RMT Configurations +# +CONFIG_RMT_ENCODER_FUNC_IN_IRAM=y +CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM=y +CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM=y +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_TX_ISR_CACHE_SAFE is not set +# CONFIG_RMT_RX_ISR_CACHE_SAFE is not set +CONFIG_RMT_OBJ_CACHE_SAFE=y +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Touch Sensor Configurations +# +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# CONFIG_TOUCH_SKIP_FSM_CHECK is not set +# end of ESP-Driver:Touch Sensor Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations + +# +# ESP-Driver:TWAI Configurations +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# CONFIG_TWAI_IO_FUNC_IN_IRAM is not set +# CONFIG_TWAI_ISR_CACHE_SAFE is not set +# CONFIG_TWAI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:TWAI Configurations + +# +# ESP-Driver:UART Configurations +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:UHCI Configurations +# +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + +# +# ESP-Driver:USB Serial/JTAG Configuration +# +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +CONFIG_ETH_SPI_ETHERNET_W5500=y +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 +CONFIG_HTTPD_MAX_URI_LEN=256 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +CONFIG_HTTPD_WS_SUPPORT=y +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# CONFIG_HTTPD_WS_PRE_HANDSHAKE_CB_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 +# CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# Chip revision +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configurations +# +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configurations + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config + +# +# Power Supplier +# + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +CONFIG_ESP_BROWNOUT_USE_INTR=y +# end of Brownout Detector +# end of Power Supplier + +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +CONFIG_ESP_INTR_IN_IRAM=y +# end of Hardware Settings + +# +# ESP-Driver:LCD Controller Configurations +# +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:LCD Controller Configurations + +# +# ESP-MM: Memory Management Configurations +# +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# PHY +# +CONFIG_ESP_PHY_ENABLED=y +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# CONFIG_ESP_PHY_DEBUG is not set +# end of PHY + +# +# Power Management +# +CONFIG_PM_SLEEP_FUNC_IN_IRAM=y +# CONFIG_PM_ENABLE is not set +CONFIG_PM_SLP_IRAM_OPT=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# +CONFIG_SPIRAM=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED=80 +# CONFIG_SPIRAM_ECC_ENABLE is not set +CONFIG_SPIRAM_BOOT_HW_INIT=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=64 +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=16384 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP-ROM +# +CONFIG_ESP_ROM_PRINT_IN_IRAM=y +# end of ESP-ROM + +# +# ESP Security Specific +# +# end of ESP Security Specific + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +CONFIG_ESP_SYSTEM_IN_IRAM=y +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4608 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=30 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_ENABLE=y +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# ESP Timer (High Resolution Timer) +# +CONFIG_ESP_TIMER_IN_IRAM=y +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=3 +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=8 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_ENABLE_SAE_H2E=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +# CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set +# end of WPS Configuration Options + +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y +# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=4 +# CONFIG_FATFS_LFN_NONE is not set +CONFIG_FATFS_LFN_HEAP=y +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_MAX_LFN=255 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +# CONFIG_FATFS_API_ENCODING_UTF_8 is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set + +# +# File system free space calculation behavior +# +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=1000 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3072 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U32=y +# CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U64 is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y +# end of Extra + +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=2 +CONFIG_FREERTOS_IN_IRAM=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# +CONFIG_LOG_VERSION_1=y +# CONFIG_LOG_VERSION_2 is not set +CONFIG_LOG_VERSION=1 + +# +# Log Level +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +# CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT is not set +CONFIG_LOG_MAXIMUM_LEVEL_DEBUG=y +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=4 + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Format + +# +# Settings +# +CONFIG_LOG_MODE_TEXT_EN=y +CONFIG_LOG_MODE_TEXT=y +# end of Settings + +CONFIG_LOG_IN_IRAM=y +# end of Log + +# +# LWIP +# +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="rm01" +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=16 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +CONFIG_LWIP_IP_FORWARD=y +CONFIG_LWIP_IPV4_NAPT=y +CONFIG_LWIP_IPV4_NAPT_PORTMAP=y +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=8 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=69 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=4096 +CONFIG_LWIP_TCP_WND_DEFAULT=4096 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=0 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set +# CONFIG_LWIP_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=3 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# CONFIG_LWIP_USE_ESP_GETADDRINFO is not set +# end of DNS + +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE=y +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_DEFAULT is not set +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +# CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=8192 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +CONFIG_MBEDTLS_HKDF_C=y +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# end of mbedTLS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# LibC +# +CONFIG_LIBC_NEWLIB=y +CONFIG_LIBC_MISC_IN_IRAM=y +CONFIG_LIBC_LOCKS_PLACE_IN_IRAM=y +CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_LIBC_STDOUT_LINE_ENDING_LF is not set +# CONFIG_LIBC_STDOUT_LINE_ENDING_CR is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_LF is not set +CONFIG_LIBC_STDIN_LINE_ENDING_CR=y +# CONFIG_LIBC_NEWLIB_NANO_FORMAT is not set +CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_LIBC_TIME_SYSCALL_USE_RTC is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_HRT is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_NONE is not set +# end of LibC + +CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y + +# +# NVS +# +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM=y +# end of NVS + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel + +# CONFIG_OPENTHREAD_DEBUG is not set +# end of OpenThread + +# +# Protocomm +# +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set +CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=y +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Ultra Low Power (ULP) Co-processor +# +# CONFIG_ULP_COPROC_ENABLED is not set + +# +# ULP Debugging Options +# +# end of ULP Debugging Options +# end of Ultra Low Power (ULP) Co-processor + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# CONFIG_UNITY_TEST_ORDER_BY_FILE_PATH_AND_LINE is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set + +# +# Hub Driver Configuration +# + +# +# Root Port configuration +# +CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250 +CONFIG_USB_HOST_RESET_HOLD_MS=30 +CONFIG_USB_HOST_RESET_RECOVERY_MS=30 +CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10 +# end of Root Port configuration + +# CONFIG_USB_HOST_HUBS_SUPPORTED is not set +# end of Hub Driver Configuration + +# CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK is not set +CONFIG_USB_OTG_SUPPORTED=y +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=16 + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y +# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set +# end of Wi-Fi Provisioning Manager + +# +# TianShanOS API Configuration +# +CONFIG_TS_API_MAX_ENDPOINTS=288 +CONFIG_TS_API_MAX_NAME_LENGTH=64 +CONFIG_TS_API_ENABLE_AUTH=y +# end of TianShanOS API Configuration + +# +# TianShanOS Automation Engine +# +CONFIG_TS_AUTOMATION_ENABLED=y +CONFIG_TS_AUTOMATION_CONFIG_PATH="/sdcard/config/automation.json" +CONFIG_TS_AUTOMATION_MAX_SOURCES=16 +CONFIG_TS_AUTOMATION_MAX_RULES=32 +CONFIG_TS_AUTOMATION_MAX_VARIABLES=512 +CONFIG_TS_AUTOMATION_TASK_STACK_SIZE=4096 +CONFIG_TS_AUTOMATION_TASK_PRIORITY=5 +# end of TianShanOS Automation Engine + +# +# TianShanOS PKI Certificate +# +CONFIG_TS_CERT_ENABLED=y +CONFIG_TS_CERT_DEFAULT_ORG="TianShanOS" +CONFIG_TS_CERT_DEFAULT_OU="Device" +CONFIG_TS_CERT_AUTO_INIT=y +CONFIG_TS_CERT_EXPIRY_WARNING_DAYS=30 +# end of TianShanOS PKI Certificate + +# +# TianShanOS Config Pack +# +CONFIG_TS_CONFIG_PACK_ENABLED=y +CONFIG_TS_CONFIG_PACK_MAX_SIZE=65536 +CONFIG_TS_CONFIG_PACK_VERIFY_CERT_CHAIN=y +# CONFIG_TS_CONFIG_PACK_REQUIRE_OFFICIAL_SIG is not set +# end of TianShanOS Config Pack + +# +# TianShanOS Console Configuration +# +CONFIG_TS_CONSOLE_MAX_LINE_LENGTH=256 +CONFIG_TS_CONSOLE_MAX_HISTORY=50 +CONFIG_TS_CONSOLE_TASK_PRIORITY=5 +CONFIG_TS_CONSOLE_TASK_STACK_SIZE=6144 +CONFIG_TS_CONSOLE_DEFAULT_PROMPT="tianshan> " +CONFIG_TS_CONSOLE_ENABLE_COLORS=y +CONFIG_TS_CONSOLE_HISTORY_FILE="/sdcard/.console_history" +# end of TianShanOS Console Configuration + +# +# TianShanOS Drivers Configuration +# +CONFIG_TS_DRIVERS_FAN_ENABLE=y +CONFIG_TS_DRIVERS_FAN_PWM_FREQ=25000 +CONFIG_TS_DRIVERS_FAN_TEMP_UPDATE_MS=1000 +CONFIG_TS_DRIVERS_POWER_ENABLE=y +CONFIG_TS_DRIVERS_POWER_ADC_SAMPLES=16 +CONFIG_TS_DRIVERS_DEVICE_ENABLE=y +CONFIG_TS_DRIVERS_AGX_POWER_ON_DELAY_MS=100 +CONFIG_TS_DRIVERS_USB_MUX_ENABLE=y +# end of TianShanOS Drivers Configuration + +# +# TianShanOS HAL Configuration +# +CONFIG_TS_HAL_MAX_PINS=48 +CONFIG_TS_HAL_MAX_GPIO_HANDLES=32 +CONFIG_TS_HAL_MAX_PWM_HANDLES=8 +CONFIG_TS_HAL_MAX_I2C_HANDLES=4 +CONFIG_TS_HAL_MAX_SPI_HANDLES=4 +CONFIG_TS_HAL_MAX_UART_HANDLES=3 +CONFIG_TS_HAL_MAX_ADC_HANDLES=8 +CONFIG_TS_HAL_PIN_CONFIG_PATH="/sdcard/config/pins.json" +CONFIG_TS_HAL_ENABLE_PIN_CONFLICT_CHECK=y +CONFIG_TS_HAL_PWM_DEFAULT_FREQ=25000 +CONFIG_TS_HAL_PWM_DEFAULT_RESOLUTION=8 +# end of TianShanOS HAL Configuration + +# +# TianShanOS HTTPS Server +# +# CONFIG_TS_HTTPS_ENABLED is not set +# end of TianShanOS HTTPS Server + +# +# TianShanOS LED Configuration +# +CONFIG_TS_LED_MAX_DEVICES=8 +CONFIG_TS_LED_MAX_LAYERS=8 +CONFIG_TS_LED_DEFAULT_BRIGHTNESS=128 +CONFIG_TS_LED_TASK_PRIORITY=5 +CONFIG_TS_LED_TASK_STACK_SIZE=3072 +CONFIG_TS_LED_REFRESH_RATE_HZ=60 + +# +# Touch LED Settings +# +CONFIG_TS_LED_TOUCH_COUNT=1 +CONFIG_TS_LED_TOUCH_DEFAULT_BRIGHTNESS=80 +# end of Touch LED Settings + +# +# Board LED Settings +# +CONFIG_TS_LED_BOARD_COUNT=28 +CONFIG_TS_LED_BOARD_DEFAULT_BRIGHTNESS=60 +# end of Board LED Settings + +# +# Matrix LED Settings +# +CONFIG_TS_LED_MATRIX_WIDTH=32 +CONFIG_TS_LED_MATRIX_HEIGHT=32 +CONFIG_TS_LED_MATRIX_DEFAULT_BRIGHTNESS=50 +# end of Matrix LED Settings + +# +# Image Support +# +CONFIG_TS_LED_ENABLE_BMP=y +CONFIG_TS_LED_ENABLE_PNG=y +CONFIG_TS_LED_ENABLE_JPG=y +CONFIG_TS_LED_ENABLE_GIF=y +# end of Image Support +# end of TianShanOS LED Configuration + +# +# TianShanOS Network Configuration +# +CONFIG_TS_NET_ETHERNET_ENABLE=y +CONFIG_TS_NET_ETH_SPI_HOST=2 +# CONFIG_TS_NET_WIFI_ENABLE is not set +CONFIG_TS_NET_DHCP_SERVER_ENABLE=y +# CONFIG_TS_NET_MDNS_ENABLE is not set +CONFIG_TS_NET_HTTP_SERVER_ENABLE=y +CONFIG_TS_NET_HTTP_PORT=80 +CONFIG_TS_NET_HTTPS_PORT=443 +# end of TianShanOS Network Configuration + +# +# TianShanOS OTA Configuration +# +CONFIG_TS_OTA_ENABLED=y +CONFIG_TS_OTA_ROLLBACK_TIMEOUT=60 +CONFIG_TS_OTA_HTTPS_ENABLED=y +CONFIG_TS_OTA_SDCARD_ENABLED=y +CONFIG_TS_OTA_WEBUI_UPLOAD_ENABLED=y +CONFIG_TS_OTA_BUFFER_SIZE=8192 +# CONFIG_TS_OTA_VERIFY_SIGNATURE is not set +# CONFIG_TS_OTA_ANTI_ROLLBACK is not set +CONFIG_TS_OTA_VERSION_CHECK=y +CONFIG_TS_OTA_DEFAULT_URL="https://ota.example.com/tianshanos" +CONFIG_TS_OTA_TASK_STACK_SIZE=8192 +CONFIG_TS_OTA_TASK_PRIORITY=5 +# end of TianShanOS OTA Configuration + +# +# TianShanOS Security Configuration +# +CONFIG_TS_SECURITY_ENABLE=y +CONFIG_TS_SECURITY_KEY_STORAGE_NVS=y +CONFIG_TS_SECURITY_MTLS_ENABLE=y +CONFIG_TS_SECURITY_TOKEN_EXPIRE_SEC=86400 +CONFIG_TS_SECURITY_MAX_SESSIONS=8 +CONFIG_TS_SECURITY_PERMISSION_LEVELS=4 +CONFIG_TS_SSH_LOG_WATCH_MAX=32 +# end of TianShanOS Security Configuration + +# +# TianShanOS Storage Configuration +# +CONFIG_TS_STORAGE_ENABLE_SPIFFS=y +CONFIG_TS_STORAGE_SPIFFS_MOUNT_POINT="/spiffs" +CONFIG_TS_STORAGE_SPIFFS_PARTITION="storage" +CONFIG_TS_STORAGE_SPIFFS_MAX_FILES=5 +CONFIG_TS_STORAGE_ENABLE_SD=y +CONFIG_TS_STORAGE_SD_MOUNT_POINT="/sdcard" +CONFIG_TS_STORAGE_SD_MAX_FREQ_KHZ=20000 +# CONFIG_TS_STORAGE_SD_MODE_SPI is not set +# CONFIG_TS_STORAGE_SD_MODE_SDIO_1BIT is not set +CONFIG_TS_STORAGE_SD_MODE_SDIO_4BIT=y + +# +# SD Card GPIO Configuration +# +CONFIG_TS_STORAGE_SD_CMD_GPIO=15 +CONFIG_TS_STORAGE_SD_CLK_GPIO=16 +CONFIG_TS_STORAGE_SD_D0_GPIO=4 +CONFIG_TS_STORAGE_SD_D1_GPIO=5 +CONFIG_TS_STORAGE_SD_D2_GPIO=6 +CONFIG_TS_STORAGE_SD_D3_GPIO=7 +# end of SD Card GPIO Configuration +# end of TianShanOS Storage Configuration + +# +# TianShanOS WebUI Configuration +# +CONFIG_TS_WEBUI_ENABLE=y +CONFIG_TS_WEBUI_API_PREFIX="/api/v1" +CONFIG_TS_WEBUI_WS_ENABLE=y +CONFIG_TS_WEBUI_WS_MAX_CLIENTS=8 +CONFIG_TS_WEBUI_TERMINAL_OUTPUT_BUF_SIZE=32768 +CONFIG_TS_WEBUI_AUTH_REQUIRED=y +CONFIG_TS_WEBUI_CORS_ENABLE=y +CONFIG_TS_WEBUI_STATIC_PATH="/www" +# end of TianShanOS WebUI Configuration + +# +# TianShanOS Configuration Management +# +CONFIG_TS_CONFIG_ENABLE=y +CONFIG_TS_CONFIG_MAX_KEY_LENGTH=64 +CONFIG_TS_CONFIG_MAX_VALUE_SIZE=512 +CONFIG_TS_CONFIG_MAX_LISTENERS=16 +CONFIG_TS_CONFIG_NVS_NAMESPACE="ts_config" + +# +# Configuration Backends +# +CONFIG_TS_CONFIG_NVS_BACKEND=y +CONFIG_TS_CONFIG_FILE_BACKEND=y +CONFIG_TS_CONFIG_FILE_PATH="/sdcard/config" +CONFIG_TS_CONFIG_FILE_FORMAT_JSON=y +# end of Configuration Backends + +# +# Configuration Priorities +# +CONFIG_TS_CONFIG_PRIORITY_CLI=100 +CONFIG_TS_CONFIG_PRIORITY_NVS=80 +CONFIG_TS_CONFIG_PRIORITY_FILE=60 +CONFIG_TS_CONFIG_PRIORITY_DEFAULT=0 +# end of Configuration Priorities + +CONFIG_TS_CONFIG_AUTO_SAVE=y +CONFIG_TS_CONFIG_AUTO_SAVE_DELAY_MS=1000 +# CONFIG_TS_CONFIG_DEBUG is not set +# end of TianShanOS Configuration Management + +# +# TianShanOS Logging +# +CONFIG_TS_LOG_ENABLE=y +# CONFIG_TS_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_TS_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_TS_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_TS_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_TS_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_TS_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_TS_LOG_DEFAULT_LEVEL=3 +CONFIG_TS_LOG_COLORS=y +CONFIG_TS_LOG_TIMESTAMP=y +CONFIG_TS_LOG_TASK_NAME=y + +# +# Log Outputs +# +CONFIG_TS_LOG_OUTPUT_CONSOLE=y +# CONFIG_TS_LOG_OUTPUT_FILE is not set +CONFIG_TS_LOG_OUTPUT_BUFFER=y +CONFIG_TS_LOG_BUFFER_SIZE=500 +CONFIG_TS_LOG_CAPTURE_ESP_LOG=y +# end of Log Outputs + +CONFIG_TS_LOG_TAG_MAX_LENGTH=16 +CONFIG_TS_LOG_MESSAGE_MAX_LENGTH=256 +# end of TianShanOS Logging + +# +# TianShanOS Event System +# +CONFIG_TS_EVENT_ENABLE=y +CONFIG_TS_EVENT_LOOP_TASK_PRIORITY=5 +CONFIG_TS_EVENT_LOOP_TASK_STACK_SIZE=4096 +CONFIG_TS_EVENT_QUEUE_SIZE=32 +CONFIG_TS_EVENT_MAX_HANDLERS=64 +CONFIG_TS_EVENT_MAX_EVENT_TYPES=64 +CONFIG_TS_EVENT_DATA_MAX_SIZE=256 +CONFIG_TS_EVENT_ENABLE_STATS=y +# CONFIG_TS_EVENT_ENABLE_TRACING is not set +# end of TianShanOS Event System + +# +# TianShanOS Service Management +# +CONFIG_TS_SERVICE_ENABLE=y +CONFIG_TS_SERVICE_MAX_SERVICES=32 +CONFIG_TS_SERVICE_NAME_MAX_LENGTH=32 +CONFIG_TS_SERVICE_MAX_DEPENDENCIES=8 +CONFIG_TS_SERVICE_STARTUP_TIMEOUT_MS=30000 +CONFIG_TS_SERVICE_SHUTDOWN_TIMEOUT_MS=10000 + +# +# Startup Phases +# +CONFIG_TS_SERVICE_PHASE_PLATFORM_PRIORITY=10 +CONFIG_TS_SERVICE_PHASE_CORE_PRIORITY=20 +CONFIG_TS_SERVICE_PHASE_HAL_PRIORITY=30 +CONFIG_TS_SERVICE_PHASE_DRIVER_PRIORITY=40 +CONFIG_TS_SERVICE_PHASE_NETWORK_PRIORITY=50 +CONFIG_TS_SERVICE_PHASE_SECURITY_PRIORITY=60 +CONFIG_TS_SERVICE_PHASE_SERVICE_PRIORITY=70 +CONFIG_TS_SERVICE_PHASE_UI_PRIORITY=80 +# end of Startup Phases + +CONFIG_TS_SERVICE_ENABLE_WATCHDOG=y +CONFIG_TS_SERVICE_WATCHDOG_TIMEOUT_MS=60000 +# CONFIG_TS_SERVICE_DEBUG is not set +# end of TianShanOS Service Management + +# +# JPEG Decoder +# +CONFIG_JD_USE_ROM=y +# end of JPEG Decoder + +# +# ESP WebSocket client +# +# CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER is not set +# CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK is not set +# end of ESP WebSocket client + +# +# mDNS +# +CONFIG_MDNS_MAX_INTERFACES=3 +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_ACTION_QUEUE_LEN=16 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 + +# +# MDNS Memory Configuration +# +# CONFIG_MDNS_TASK_CREATE_FROM_SPIRAM is not set +CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL=y +# CONFIG_MDNS_MEMORY_ALLOC_SPIRAM is not set +CONFIG_MDNS_MEMORY_ALLOC_INTERNAL=y +# CONFIG_MDNS_MEMORY_CUSTOM_IMPL is not set +# end of MDNS Memory Configuration + +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +# CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES is not set +# CONFIG_MDNS_ENABLE_DEBUG_PRINTS is not set +CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +# CONFIG_MDNS_RESPOND_REVERSE_QUERIES is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y + +# +# MDNS Predefined interfaces +# +CONFIG_MDNS_PREDEF_NETIF_STA=y +CONFIG_MDNS_PREDEF_NETIF_AP=y +CONFIG_MDNS_PREDEF_NETIF_ETH=y +# end of MDNS Predefined interfaces +# end of mDNS +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +CONFIG_FLASHMODE_QIO=y +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +CONFIG_OTA_ALLOW_HTTP=y +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=3584 +CONFIG_MAIN_TASK_STACK_SIZE=4608 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=30 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=8 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=3072 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=8 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=4096 +CONFIG_TCP_WND_DEFAULT=4096 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/docs/repair/ssh-poll-stack/change.patch b/docs/repair/ssh-poll-stack/change.patch new file mode 100644 index 0000000..3d45042 --- /dev/null +++ b/docs/repair/ssh-poll-stack/change.patch @@ -0,0 +1,98 @@ +diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c +index 9bc83dc..b79cb47 100644 +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -50,6 +50,7 @@ + + /* SSH Shell 输出缓冲区大小 */ + #define SSH_OUTPUT_BUF_SIZE 2048 ++#define SSH_POLL_STACK_SIZE 8192 + + typedef enum { + WS_CLIENT_TYPE_EVENT, // 普通事件订阅客户端 +@@ -271,7 +272,7 @@ static void ssh_poll_task(void *arg) + } + shell_resources_close(ctx); + ts_ws_op_executor_done(op); +- vTaskDelete(NULL); ++ vTaskDeleteWithCaps(NULL); + } + static void ssh_cleanup(void) + { +@@ -308,7 +309,7 @@ static void handle_ssh_connect(httpd_req_t *req,cJSON *params) + error="Failed to open shell"; + if(ts_ssh_shell_open(ctx->session,&shell_config,&ctx->shell)!=ESP_OK)goto failed; + ts_ws_op_executor_take(op); +- if(xTaskCreateWithCaps(ssh_poll_task,"ssh_poll",4096,ctx,5,NULL,MALLOC_CAP_SPIRAM)!=pdPASS){ts_ws_op_executor_done(op);error="Failed to create SSH session";goto failed;} ++ if(xTaskCreateWithCaps(ssh_poll_task,"ssh_poll",SSH_POLL_STACK_SIZE,ctx,5,NULL,MALLOC_CAP_SPIRAM)!=pdPASS){ts_ws_op_executor_done(op);error="Failed to create SSH session";goto failed;} + poller=true;error="SSH shell closed during startup"; + if(!ts_ssh_shell_is_active(ctx->shell))goto failed; + error="SSH readiness delivery failed"; +diff --git a/tests/ws_subscriptions/test_operation_adapter.c b/tests/ws_subscriptions/test_operation_adapter.c +index 4a98321..d0e6245 100644 +--- a/tests/ws_subscriptions/test_operation_adapter.c ++++ b/tests/ws_subscriptions/test_operation_adapter.c +@@ -42,6 +42,8 @@ static char *host_strdup(const char *s){size_t n=strlen(s)+1;char *p=tracked_mal + static char *host_strndup(const char *s,size_t n){char *p=tracked_malloc(n+1);if(p){memcpy(p,s,n);p[n]=0;}return p;} + static struct {void (*fn)(void *);void *arg;} shell_task,exec_task; + static bool task_create_fail,close_during_create,inline_exec; ++static unsigned caps_deletes; ++static void adapter_delete_caps(TaskHandle_t task); + static int adapter_create(void(*fn)(void*),const char *name,unsigned stack,void *arg,unsigned priority,TaskHandle_t *out){ + (void)stack;(void)priority;(void)out;if(task_create_fail)return 0; + if(!strcmp(name,"ssh_poll"))shell_task=(typeof(shell_task)){fn,arg};else exec_task=(typeof(exec_task)){fn,arg}; +@@ -58,7 +60,9 @@ static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,voi + #define heap_caps_calloc host_heap_calloc + #define xTaskCreate adapter_create + #define xTaskCreateWithCaps adapter_create_caps ++#define vTaskDeleteWithCaps adapter_delete_caps + #include "ts_webui_ws.c" ++_Static_assert(SSH_POLL_STACK_SIZE == 8192, "SSH poll stack budget is bytes"); + #undef malloc + #undef calloc + #undef free +@@ -68,6 +72,7 @@ static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,voi + #undef heap_caps_calloc + #undef xTaskCreate + #undef xTaskCreateWithCaps ++#undef vTaskDeleteWithCaps + #ifndef PROJECT_REAL_DRIVER + struct ts_ssh_session_s {bool aborted;ts_ssh_config_t config;}; + #endif +@@ -130,11 +135,21 @@ esp_err_t ts_log_remove_callback(ts_log_callback_handle_t h){(void)h;return remo + size_t ts_log_buffer_search(ts_log_entry_t *e,size_t n,ts_log_level_t min,ts_log_level_t max,const char *tag,const char *keyword){(void)e;(void)n;(void)min;(void)max;(void)tag;(void)keyword;return 0;} + httpd_handle_t ts_http_server_get_handle(void){return (void*)11;} + void ts_http_server_set_stop_hooks(esp_err_t(*stop)(httpd_handle_t),void(*stopped)(httpd_handle_t)){(void)stop;(void)stopped;} +-static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){(void)caps; ++static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){ ++assert(!strcmp(n,"ssh_poll") && stack==8192 && caps==MALLOC_CAP_SPIRAM); + #ifndef PROJECT_REAL_DRIVER + if(close_during_create)((ssh_shell_context_t*)arg)->shell->active=false; + #endif + return adapter_create(fn,n,stack,arg,p,out);} ++static void adapter_delete_caps(TaskHandle_t task){ ++ assert(!task); ++ ts_ws_op_stats_t ledger;ts_ws_op_stats(TS_WS_OP_SHELL,&ledger); ++ assert(!ledger.executors); ++ /* The original context remains pinned until queued terminal settlement. */ ++ ts_ws_operation_t *op=ts_ws_op_shell_owner(); ++ if(op){ssh_shell_context_t *ctx=ts_ws_op_data(op);assert(!ctx->shell && !ctx->session);ts_ws_op_release(op);} ++ caps_deletes++; ++} + static void drive_all(void){for(unsigned i=0;i<12;i++){ts_ws_op_poll();pump();timer_pump();}assert(!timer_queued);} + static void setup(void){start();memset(s_clients,0,sizeof(s_clients));s_server=(void*)11;s_ws_stopping=false;ts_ws_op_enable();transport_server.closed=peer_closed;for(int fd=1;fd<=2;fd++){reqs[fd]=(httpd_req_t){.handle=(void*)11,.fd=fd};current=(void*)3;assert(add_client(&reqs[fd],WS_CLIENT_TYPE_EVENT)==ESP_OK);}current=(void*)1;} + static void finish_all(void){drive_all();assert(!ts_ws_op_busy());stop();assert(!live_allocations);} +@@ -292,6 +307,13 @@ int main(void){ + assert(ts_webui_ssh_exec_start_ex("fake",22,"user",NULL,"password","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);drive_all();assert(terminal_frames==2 && !output_after_terminal && variable_writes);finish_all(); + setup();inline_exec=true;assert(ts_webui_ssh_exec_start("fake",22,"user",NULL,"password","cmd",&id)==0);inline_exec=false;finish_all(); ++ for(unsigned i=0;i<10;i++){ ++ setup();connect_shell();unsigned before=caps_deletes; ++ ssh_cleanup();shell_task.fn(shell_task.arg); ++ assert(caps_deletes==before+1);finish_all(); ++ ts_ws_op_stats_t ledger;ts_ws_op_stats(TS_WS_OP_SHELL,&ledger); ++ assert(ledger.phase==OP_FREE && !ledger.refs && !ledger.executors); ++ } + operation_cross_tests(); + printf("PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=%u\n",session_destroys); + return 0; diff --git a/docs/repair/ssh-poll-stack/crash.txt b/docs/repair/ssh-poll-stack/crash.txt new file mode 100644 index 0000000..7ff88de --- /dev/null +++ b/docs/repair/ssh-poll-stack/crash.txt @@ -0,0 +1,30 @@ + need_streaming=0, current=0 +I (92696) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (93748) ts_ssh: SSH client initialized (libssh2 version: 1.10.1_DEV) +I (94318) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (94718) ts_shell: Interactive shell opened + +***ERROR*** A stack overflow in task ssh_poll has been detected. + + +Backtrace: 0x4037ebfd:0x3c2dc980 0x4037ebc5:0x3c2dc9a0 0x4037fcf2:0x3c2dc9c0 0x40381793:0x3c2dca40 0x4037fdb8:0x3c2dca60 0x4037fdae:0xa5a5a5a5 |<-CORRUPTED + + + + +ELF file SHA256: 6265f4e96 + +Rebooting... +ESP-ROM:esp32s3-20210327 +Build:Mar 27 2021 +rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT) +Saved PC:0x4037ed9d +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3fce2820,len:0x1700 +load:0x403c8700,len:0xec0 +load:0x403cb700,len:0x31c0 +entry 0x403c894c +I (24) boot: ESP-IDF v5.5.2 2nd stage bootloader +I (24) boot: compile time Sep 28 2026 17:09:05 +I (24) boot: M \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/flash.log b/docs/repair/ssh-poll-stack/device-candidate/flash.log new file mode 100644 index 0000000..66071cf --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/flash.log @@ -0,0 +1,233 @@ +Checking "python3" ... +Python 3.12.4 +"python3" has been detected +Activating ESP-IDF 5.5 +Setting IDF_PATH to '/Users/massif/esp/v5.5.2/esp-idf'. +* Checking python version ... 3.12.4 +* Checking python dependencies ... OK +* Deactivating the current ESP-IDF environment (if any) ... OK +* Establishing a new ESP-IDF environment ... OK +* Identifying shell ... zsh +* Detecting outdated tools in system ... Found tools that are not used by active ESP-IDF version. +For removing old versions of riscv32-esp-elf, cmake, xtensa-esp-elf, openocd-esp32, esp-rom-elfs, xtensa-esp-elf-gdb, riscv32-esp-elf-gdb use command 'python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall' +To free up even more space, remove installation packages of those tools. +Use option python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall --remove-archives. +* Shell completion ... Autocompletion code generated + +Done! You can now compile ESP-IDF projects. +Go to the project directory and run: + + idf.py build +Executing action: flash +Running ninja in directory /private/tmp/tianshan-ssh-stack-candidate/build +Executing "ninja flash"... +[1/6] cd /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ssh-stack-candidate/build/partition_table/partition-table.bin /tmp/tianshan-ssh-stack-candidate/build/TianShanOS.bin +TianShanOS.bin binary size 0x215120 bytes. Smallest app partition is 0x300000 bytes. 0xeaee0 bytes (31%) free. +[2/6] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-ssh-stack-candidate/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ssh-stack-candidate/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[3/6] No install step for 'bootloader' +[4/6] cd /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ssh-stack-candidate/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[5/6] Completed 'bootloader' +[5/6] cd /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py && /Users/massif/.espressif/tools/cmake/3.30.2/CMake.app/Contents/bin/cmake -D IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf -D "SERIAL_TOOL=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python;;/Users/massif/esp/v5.5.2/esp-idf/components/esptool_py/esptool/esptool.py;--chip;esp32s3" -D "SERIAL_TOOL_ARGS=--before=default_reset;--after=hard_reset;write_flash;@flash_args" -D WORKING_DIRECTORY=/tmp/tianshan-ssh-stack-candidate/build -P /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py/run_serial_tool.cmake +esptool.py --chip esp32s3 -p /dev/cu.usbmodem11401 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x20000 TianShanOS.bin 0x8000 partition_table/partition-table.bin 0x16000 ota_data_initial.bin 0x6a0000 www.bin +esptool.py v4.12.dev2 +Serial port /dev/cu.usbmodem11401 +Connecting... +Chip is ESP32-S3 (QFN56) (revision v0.2) +Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3) +Crystal is 40MHz +USB mode: USB-Serial/JTAG +MAC: 20:6e:f1:a1:d5:8c +Uploading stub... +Running stub... +Stub running... +Changing baud rate to 460800 +Changed. +Configuring flash size... +Flash will be erased from 0x00000000 to 0x00005fff... +Flash will be erased from 0x00020000 to 0x00235fff... +Flash will be erased from 0x00008000 to 0x00008fff... +Flash will be erased from 0x00016000 to 0x00017fff... +Flash will be erased from 0x006a0000 to 0x0099ffff... +SHA digest in image updated +Compressed 22496 bytes to 14268... +Writing at 0x00000000... (100 %) +Wrote 22496 bytes (14268 compressed) at 0x00000000 in 0.2 seconds (effective 772.9 kbit/s)... +Hash of data verified. +Compressed 2183456 bytes to 1263518... +Writing at 0x00020000... (1 %) +Writing at 0x0002d6dd... (2 %) +Writing at 0x0003a71d... (3 %) +Writing at 0x000484b4... (5 %) +Writing at 0x0005521d... (6 %) +Writing at 0x00063d24... (7 %) +Writing at 0x00072802... (8 %) +Writing at 0x0008112c... (10 %) +Writing at 0x0008ccac... (11 %) +Writing at 0x00091c05... (12 %) +Writing at 0x00097a9e... (14 %) +Writing at 0x0009c625... (15 %) +Writing at 0x000a1481... (16 %) +Writing at 0x000a67ff... (17 %) +Writing at 0x000ae703... (19 %) +Writing at 0x000ba623... (20 %) +Writing at 0x000c1041... (21 %) +Writing at 0x000c81ff... (23 %) +Writing at 0x000ce459... (24 %) +Writing at 0x000d50ef... (25 %) +Writing at 0x000db231... (26 %) +Writing at 0x000e15af... (28 %) +Writing at 0x000e7467... (29 %) +Writing at 0x000ed190... (30 %) +Writing at 0x000f2f45... (32 %) +Writing at 0x000f88c0... (33 %) +Writing at 0x000fe6c4... (34 %) +Writing at 0x001043db... (35 %) +Writing at 0x0010aa9a... (37 %) +Writing at 0x001103e6... (38 %) +Writing at 0x001161f1... (39 %) +Writing at 0x0011c34d... (41 %) +Writing at 0x001224fd... (42 %) +Writing at 0x00128680... (43 %) +Writing at 0x0012e957... (44 %) +Writing at 0x00134ac3... (46 %) +Writing at 0x0013abb4... (47 %) +Writing at 0x001411d5... (48 %) +Writing at 0x00147993... (50 %) +Writing at 0x0014dba3... (51 %) +Writing at 0x0015441e... (52 %) +Writing at 0x0015a5a0... (53 %) +Writing at 0x00160d44... (55 %) +Writing at 0x00166ef8... (56 %) +Writing at 0x0016cf42... (57 %) +Writing at 0x001737ac... (58 %) +Writing at 0x001794f2... (60 %) +Writing at 0x0017f67f... (61 %) +Writing at 0x0018593a... (62 %) +Writing at 0x0018bacf... (64 %) +Writing at 0x00191cc1... (65 %) +Writing at 0x001978b4... (66 %) +Writing at 0x0019d7aa... (67 %) +Writing at 0x001a362b... (69 %) +Writing at 0x001a91c2... (70 %) +Writing at 0x001af3d3... (71 %) +Writing at 0x001b563e... (73 %) +Writing at 0x001bbb88... (74 %) +Writing at 0x001c1f49... (75 %) +Writing at 0x001c7e5e... (76 %) +Writing at 0x001cd96b... (78 %) +Writing at 0x001d3bcc... (79 %) +Writing at 0x001d98fb... (80 %) +Writing at 0x001df9f1... (82 %) +Writing at 0x001e4ef4... (83 %) +Writing at 0x001ea174... (84 %) +Writing at 0x001ef7a2... (85 %) +Writing at 0x001f49c0... (87 %) +Writing at 0x001faa91... (88 %) +Writing at 0x002002da... (89 %) +Writing at 0x0020673c... (91 %) +Writing at 0x0020d4a7... (92 %) +Writing at 0x00214a5f... (93 %) +Writing at 0x0021b72f... (94 %) +Writing at 0x00221ae7... (96 %) +Writing at 0x00227b2f... (97 %) +Writing at 0x0022e27b... (98 %) +Writing at 0x00234311... (100 %) +Wrote 2183456 bytes (1263518 compressed) at 0x00020000 in 11.6 seconds (effective 1512.2 kbit/s)... +Hash of data verified. +Compressed 3072 bytes to 180... +Writing at 0x00008000... (100 %) +Wrote 3072 bytes (180 compressed) at 0x00008000 in 0.0 seconds (effective 726.3 kbit/s)... +Hash of data verified. +Compressed 8192 bytes to 31... +Writing at 0x00016000... (100 %) +Wrote 8192 bytes (31 compressed) at 0x00016000 in 0.0 seconds (effective 1425.2 kbit/s)... +Hash of data verified. +Compressed 3145728 bytes to 1301907... +Writing at 0x006a0000... (1 %) +Writing at 0x006a457e... (2 %) +Writing at 0x006a89e3... (3 %) +Writing at 0x006b047c... (5 %) +Writing at 0x006baf69... (6 %) +Writing at 0x006d1206... (7 %) +Writing at 0x006da3ed... (8 %) +Writing at 0x006def13... (10 %) +Writing at 0x006e398f... (11 %) +Writing at 0x006e81c3... (12 %) +Writing at 0x006ec7fd... (13 %) +Writing at 0x006f0d22... (15 %) +Writing at 0x006f5a46... (16 %) +Writing at 0x006faa98... (17 %) +Writing at 0x006fefab... (18 %) +Writing at 0x007035af... (20 %) +Writing at 0x007082a8... (21 %) +Writing at 0x0070c80f... (22 %) +Writing at 0x007122f1... (23 %) +Writing at 0x007195c7... (25 %) +Writing at 0x0071e795... (26 %) +Writing at 0x00724b4d... (27 %) +Writing at 0x00729ad6... (28 %) +Writing at 0x0072de98... (30 %) +Writing at 0x00732372... (31 %) +Writing at 0x00736749... (32 %) +Writing at 0x0073ab18... (33 %) +Writing at 0x0073eee3... (35 %) +Writing at 0x007433b1... (36 %) +Writing at 0x007477a8... (37 %) +Writing at 0x0074bb76... (38 %) +Writing at 0x0074ff3f... (40 %) +Writing at 0x0075447a... (41 %) +Writing at 0x0075c5f8... (42 %) +Writing at 0x00769000... (43 %) +Writing at 0x00778601... (45 %) +Writing at 0x00789b0f... (46 %) +Writing at 0x0079ac96... (47 %) +Writing at 0x007af271... (48 %) +Writing at 0x007bf6f8... (50 %) +Writing at 0x007d0f1b... (51 %) +Writing at 0x007e45da... (52 %) +Writing at 0x007f75ac... (53 %) +Writing at 0x00807e03... (55 %) +Writing at 0x0081a13e... (56 %) +Writing at 0x0082d777... (57 %) +Writing at 0x0083fde1... (58 %) +Writing at 0x0085163b... (60 %) +Writing at 0x0085ee5a... (61 %) +Writing at 0x0086c200... (62 %) +Writing at 0x008775dc... (63 %) +Writing at 0x00883eaf... (65 %) +Writing at 0x008903ff... (66 %) +Writing at 0x00897717... (67 %) +Writing at 0x0089ba87... (68 %) +Writing at 0x0089feb5... (70 %) +Writing at 0x008a4410... (71 %) +Writing at 0x008a884e... (72 %) +Writing at 0x008acbf6... (73 %) +Writing at 0x008b17d0... (75 %) +Writing at 0x008b5b99... (76 %) +Writing at 0x008b9f62... (77 %) +Writing at 0x008be429... (78 %) +Writing at 0x008c27e8... (80 %) +Writing at 0x008c6bba... (81 %) +Writing at 0x008caf7b... (82 %) +Writing at 0x008cf43f... (83 %) +Writing at 0x008d3802... (85 %) +Writing at 0x008d7bc6... (86 %) +Writing at 0x008dbf87... (87 %) +Writing at 0x008e0a40... (88 %) +Writing at 0x008e6b82... (90 %) +Writing at 0x008eaf45... (91 %) +Writing at 0x008ef3fe... (92 %) +Writing at 0x008f3874... (93 %) +Writing at 0x008fc62d... (95 %) +Writing at 0x0090dc54... (96 %) +Writing at 0x0091db75... (97 %) +Writing at 0x0092f6a7... (98 %) +Writing at 0x0093dbfb... (100 %) +Wrote 3145728 bytes (1301907 compressed) at 0x006a0000 in 14.5 seconds (effective 1737.0 kbit/s)... +Hash of data verified. + +Leaving... +Hard resetting via RTS pin... +Done diff --git a/docs/repair/ssh-poll-stack/device-candidate/output-input-resize.json b/docs/repair/ssh-poll-stack/device-candidate/output-input-resize.json new file mode 100644 index 0000000..8de15b4 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/output-input-resize.json @@ -0,0 +1,229 @@ +{ + "stage": "output_input_resize", + "time": "2026-09-28T18:13:04.719323", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "ready" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "ssh_poll", + "priority": 5, + "stack_hwm": 4096, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + } + ], + "count": 25 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7601348, + "min_free_heap": 7550256, + "internal": { + "total": 308035, + "free": 72459, + "allocated": 235576, + "largest_block": 31744 + }, + "psram": { + "total": 8370236, + "free": 7544404, + "allocated": 825832, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 188304 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/restore-flash.log b/docs/repair/ssh-poll-stack/device-candidate/restore-flash.log new file mode 100644 index 0000000..cfc86d2 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/restore-flash.log @@ -0,0 +1,233 @@ +Checking "python3" ... +Python 3.12.4 +"python3" has been detected +Activating ESP-IDF 5.5 +Setting IDF_PATH to '/Users/massif/esp/v5.5.2/esp-idf'. +* Checking python version ... 3.12.4 +* Checking python dependencies ... OK +* Deactivating the current ESP-IDF environment (if any) ... OK +* Establishing a new ESP-IDF environment ... OK +* Identifying shell ... zsh +* Detecting outdated tools in system ... Found tools that are not used by active ESP-IDF version. +For removing old versions of riscv32-esp-elf, cmake, xtensa-esp-elf, openocd-esp32, esp-rom-elfs, xtensa-esp-elf-gdb, riscv32-esp-elf-gdb use command 'python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall' +To free up even more space, remove installation packages of those tools. +Use option python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall --remove-archives. +* Shell completion ... Autocompletion code generated + +Done! You can now compile ESP-IDF projects. +Go to the project directory and run: + + idf.py build +Executing action: flash +Running ninja in directory /private/tmp/tianshan-ssh-stack-candidate/build +Executing "ninja flash"... +[1/6] cd /tmp/tianshan-ssh-stack-candidate/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ssh-stack-candidate/build/partition_table/partition-table.bin /tmp/tianshan-ssh-stack-candidate/build/TianShanOS.bin +TianShanOS.bin binary size 0x215120 bytes. Smallest app partition is 0x300000 bytes. 0xeaee0 bytes (31%) free. +[2/6] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-ssh-stack-candidate/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ssh-stack-candidate/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[3/6] No install step for 'bootloader' +[4/6] cd /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ssh-stack-candidate/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ssh-stack-candidate/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[5/6] Completed 'bootloader' +[5/6] cd /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py && /Users/massif/.espressif/tools/cmake/3.30.2/CMake.app/Contents/bin/cmake -D IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf -D "SERIAL_TOOL=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python;;/Users/massif/esp/v5.5.2/esp-idf/components/esptool_py/esptool/esptool.py;--chip;esp32s3" -D "SERIAL_TOOL_ARGS=--before=default_reset;--after=hard_reset;write_flash;@flash_args" -D WORKING_DIRECTORY=/tmp/tianshan-ssh-stack-candidate/build -P /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py/run_serial_tool.cmake +esptool.py --chip esp32s3 -p /dev/cu.usbmodem11401 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x20000 TianShanOS.bin 0x8000 partition_table/partition-table.bin 0x16000 ota_data_initial.bin 0x6a0000 www.bin +esptool.py v4.12.dev2 +Serial port /dev/cu.usbmodem11401 +Connecting... +Chip is ESP32-S3 (QFN56) (revision v0.2) +Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3) +Crystal is 40MHz +USB mode: USB-Serial/JTAG +MAC: 20:6e:f1:a1:d5:8c +Uploading stub... +Running stub... +Stub running... +Changing baud rate to 460800 +Changed. +Configuring flash size... +Flash will be erased from 0x00000000 to 0x00005fff... +Flash will be erased from 0x00020000 to 0x00235fff... +Flash will be erased from 0x00008000 to 0x00008fff... +Flash will be erased from 0x00016000 to 0x00017fff... +Flash will be erased from 0x006a0000 to 0x0099ffff... +SHA digest in image updated +Compressed 22496 bytes to 14268... +Writing at 0x00000000... (100 %) +Wrote 22496 bytes (14268 compressed) at 0x00000000 in 0.2 seconds (effective 768.9 kbit/s)... +Hash of data verified. +Compressed 2183456 bytes to 1263518... +Writing at 0x00020000... (1 %) +Writing at 0x0002d6dd... (2 %) +Writing at 0x0003a71d... (3 %) +Writing at 0x000484b4... (5 %) +Writing at 0x0005521d... (6 %) +Writing at 0x00063d24... (7 %) +Writing at 0x00072802... (8 %) +Writing at 0x0008112c... (10 %) +Writing at 0x0008ccac... (11 %) +Writing at 0x00091c05... (12 %) +Writing at 0x00097a9e... (14 %) +Writing at 0x0009c625... (15 %) +Writing at 0x000a1481... (16 %) +Writing at 0x000a67ff... (17 %) +Writing at 0x000ae703... (19 %) +Writing at 0x000ba623... (20 %) +Writing at 0x000c1041... (21 %) +Writing at 0x000c81ff... (23 %) +Writing at 0x000ce459... (24 %) +Writing at 0x000d50ef... (25 %) +Writing at 0x000db231... (26 %) +Writing at 0x000e15af... (28 %) +Writing at 0x000e7467... (29 %) +Writing at 0x000ed190... (30 %) +Writing at 0x000f2f45... (32 %) +Writing at 0x000f88c0... (33 %) +Writing at 0x000fe6c4... (34 %) +Writing at 0x001043db... (35 %) +Writing at 0x0010aa9a... (37 %) +Writing at 0x001103e6... (38 %) +Writing at 0x001161f1... (39 %) +Writing at 0x0011c34d... (41 %) +Writing at 0x001224fd... (42 %) +Writing at 0x00128680... (43 %) +Writing at 0x0012e957... (44 %) +Writing at 0x00134ac3... (46 %) +Writing at 0x0013abb4... (47 %) +Writing at 0x001411d5... (48 %) +Writing at 0x00147993... (50 %) +Writing at 0x0014dba3... (51 %) +Writing at 0x0015441e... (52 %) +Writing at 0x0015a5a0... (53 %) +Writing at 0x00160d44... (55 %) +Writing at 0x00166ef8... (56 %) +Writing at 0x0016cf42... (57 %) +Writing at 0x001737ac... (58 %) +Writing at 0x001794f2... (60 %) +Writing at 0x0017f67f... (61 %) +Writing at 0x0018593a... (62 %) +Writing at 0x0018bacf... (64 %) +Writing at 0x00191cc1... (65 %) +Writing at 0x001978b4... (66 %) +Writing at 0x0019d7aa... (67 %) +Writing at 0x001a362b... (69 %) +Writing at 0x001a91c2... (70 %) +Writing at 0x001af3d3... (71 %) +Writing at 0x001b563e... (73 %) +Writing at 0x001bbb88... (74 %) +Writing at 0x001c1f49... (75 %) +Writing at 0x001c7e5e... (76 %) +Writing at 0x001cd96b... (78 %) +Writing at 0x001d3bcc... (79 %) +Writing at 0x001d98fb... (80 %) +Writing at 0x001df9f1... (82 %) +Writing at 0x001e4ef4... (83 %) +Writing at 0x001ea174... (84 %) +Writing at 0x001ef7a2... (85 %) +Writing at 0x001f49c0... (87 %) +Writing at 0x001faa91... (88 %) +Writing at 0x002002da... (89 %) +Writing at 0x0020673c... (91 %) +Writing at 0x0020d4a7... (92 %) +Writing at 0x00214a5f... (93 %) +Writing at 0x0021b72f... (94 %) +Writing at 0x00221ae7... (96 %) +Writing at 0x00227b2f... (97 %) +Writing at 0x0022e27b... (98 %) +Writing at 0x00234311... (100 %) +Wrote 2183456 bytes (1263518 compressed) at 0x00020000 in 11.6 seconds (effective 1510.0 kbit/s)... +Hash of data verified. +Compressed 3072 bytes to 180... +Writing at 0x00008000... (100 %) +Wrote 3072 bytes (180 compressed) at 0x00008000 in 0.0 seconds (effective 691.3 kbit/s)... +Hash of data verified. +Compressed 8192 bytes to 31... +Writing at 0x00016000... (100 %) +Wrote 8192 bytes (31 compressed) at 0x00016000 in 0.0 seconds (effective 1394.3 kbit/s)... +Hash of data verified. +Compressed 3145728 bytes to 1301907... +Writing at 0x006a0000... (1 %) +Writing at 0x006a457e... (2 %) +Writing at 0x006a89e3... (3 %) +Writing at 0x006b047c... (5 %) +Writing at 0x006baf69... (6 %) +Writing at 0x006d1206... (7 %) +Writing at 0x006da3ed... (8 %) +Writing at 0x006def13... (10 %) +Writing at 0x006e398f... (11 %) +Writing at 0x006e81c3... (12 %) +Writing at 0x006ec7fd... (13 %) +Writing at 0x006f0d22... (15 %) +Writing at 0x006f5a46... (16 %) +Writing at 0x006faa98... (17 %) +Writing at 0x006fefab... (18 %) +Writing at 0x007035af... (20 %) +Writing at 0x007082a8... (21 %) +Writing at 0x0070c80f... (22 %) +Writing at 0x007122f1... (23 %) +Writing at 0x007195c7... (25 %) +Writing at 0x0071e795... (26 %) +Writing at 0x00724b4d... (27 %) +Writing at 0x00729ad6... (28 %) +Writing at 0x0072de98... (30 %) +Writing at 0x00732372... (31 %) +Writing at 0x00736749... (32 %) +Writing at 0x0073ab18... (33 %) +Writing at 0x0073eee3... (35 %) +Writing at 0x007433b1... (36 %) +Writing at 0x007477a8... (37 %) +Writing at 0x0074bb76... (38 %) +Writing at 0x0074ff3f... (40 %) +Writing at 0x0075447a... (41 %) +Writing at 0x0075c5f8... (42 %) +Writing at 0x00769000... (43 %) +Writing at 0x00778601... (45 %) +Writing at 0x00789b0f... (46 %) +Writing at 0x0079ac96... (47 %) +Writing at 0x007af271... (48 %) +Writing at 0x007bf6f8... (50 %) +Writing at 0x007d0f1b... (51 %) +Writing at 0x007e45da... (52 %) +Writing at 0x007f75ac... (53 %) +Writing at 0x00807e03... (55 %) +Writing at 0x0081a13e... (56 %) +Writing at 0x0082d777... (57 %) +Writing at 0x0083fde1... (58 %) +Writing at 0x0085163b... (60 %) +Writing at 0x0085ee5a... (61 %) +Writing at 0x0086c200... (62 %) +Writing at 0x008775dc... (63 %) +Writing at 0x00883eaf... (65 %) +Writing at 0x008903ff... (66 %) +Writing at 0x00897717... (67 %) +Writing at 0x0089ba87... (68 %) +Writing at 0x0089feb5... (70 %) +Writing at 0x008a4410... (71 %) +Writing at 0x008a884e... (72 %) +Writing at 0x008acbf6... (73 %) +Writing at 0x008b17d0... (75 %) +Writing at 0x008b5b99... (76 %) +Writing at 0x008b9f62... (77 %) +Writing at 0x008be429... (78 %) +Writing at 0x008c27e8... (80 %) +Writing at 0x008c6bba... (81 %) +Writing at 0x008caf7b... (82 %) +Writing at 0x008cf43f... (83 %) +Writing at 0x008d3802... (85 %) +Writing at 0x008d7bc6... (86 %) +Writing at 0x008dbf87... (87 %) +Writing at 0x008e0a40... (88 %) +Writing at 0x008e6b82... (90 %) +Writing at 0x008eaf45... (91 %) +Writing at 0x008ef3fe... (92 %) +Writing at 0x008f3874... (93 %) +Writing at 0x008fc62d... (95 %) +Writing at 0x0090dc54... (96 %) +Writing at 0x0091db75... (97 %) +Writing at 0x0092f6a7... (98 %) +Writing at 0x0093dbfb... (100 %) +Wrote 3145728 bytes (1301907 compressed) at 0x006a0000 in 14.5 seconds (effective 1738.0 kbit/s)... +Hash of data verified. + +Leaving... +Hard resetting via RTS pin... +Done diff --git a/docs/repair/ssh-poll-stack/device-candidate/restore-health.json b/docs/repair/ssh-poll-stack/device-candidate/restore-health.json new file mode 100644 index 0000000..c41961c --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/restore-health.json @@ -0,0 +1,220 @@ +{ + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 14827 + } + }, + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 5368, + "core": 2147483647, + "state": "running" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1824, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1388, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2824, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 536, + "core": 0, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1628, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15152, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2488, + "core": 0, + "state": "suspended" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 3812, + "core": 2147483647, + "state": "suspended" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 528, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7674516, + "min_free_heap": 7645272, + "internal": { + "total": 308167, + "free": 74279, + "allocated": 233888, + "largest_block": 31744 + }, + "psram": { + "total": 8370364, + "free": 7615760, + "allocated": 754604, + "largest_block": 7602176 + } + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round1-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round1-closed.json new file mode 100644 index 0000000..016927e --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round1-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round1_closed_local_help", + "time": "2026-09-28T18:15:15.752403", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7672364, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370332, + "free": 7614416, + "allocated": 755916, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 319336 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round10-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round10-closed.json new file mode 100644 index 0000000..831455f --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round10-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round10_closed", + "time": "2026-09-28T18:23:11.863874", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1060, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1564, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2504, + "core": 0, + "state": "suspended" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671576, + "min_free_heap": 7549148, + "internal": { + "total": 308083, + "free": 73359, + "allocated": 234724, + "largest_block": 31744 + }, + "psram": { + "total": 8370312, + "free": 7613736, + "allocated": 756576, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 795443 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round2-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round2-closed.json new file mode 100644 index 0000000..2b1b46a --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round2-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round2_closed", + "time": "2026-09-28T18:16:04.490257", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7672156, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370328, + "free": 7614208, + "allocated": 756120, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 368074 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round3-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round3-closed.json new file mode 100644 index 0000000..755ab04 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round3-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round3_closed", + "time": "2026-09-28T18:16:44.614563", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671944, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370324, + "free": 7613996, + "allocated": 756328, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 408198 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round4-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round4-closed.json new file mode 100644 index 0000000..4051178 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round4-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round4_closed", + "time": "2026-09-28T18:17:44.745380", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "ready" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671944, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370324, + "free": 7613996, + "allocated": 756328, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 468330 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round5-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round5-closed.json new file mode 100644 index 0000000..4039ef9 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round5-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round5_closed", + "time": "2026-09-28T18:18:53.414995", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671940, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370324, + "free": 7613996, + "allocated": 756328, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 536996 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round6-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round6-closed.json new file mode 100644 index 0000000..9b3923c --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round6-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round6_closed", + "time": "2026-09-28T18:19:31.243581", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671940, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370324, + "free": 7613996, + "allocated": 756328, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 574826 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round7-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round7-closed.json new file mode 100644 index 0000000..b608041 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round7-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round7_closed", + "time": "2026-09-28T18:20:26.377107", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671720, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370320, + "free": 7613768, + "allocated": 756552, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 629959 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round8-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round8-closed.json new file mode 100644 index 0000000..216896a --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round8-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round8_closed", + "time": "2026-09-28T18:21:21.129939", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "ready" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7670896, + "min_free_heap": 7550256, + "internal": { + "total": 308075, + "free": 73203, + "allocated": 234872, + "largest_block": 31744 + }, + "psram": { + "total": 8370292, + "free": 7613204, + "allocated": 757088, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 684751 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/round9-closed.json b/docs/repair/ssh-poll-stack/device-candidate/round9-closed.json new file mode 100644 index 0000000..e782f77 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/round9-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round9_closed", + "time": "2026-09-28T18:22:25.667469", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1564, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7671940, + "min_free_heap": 7550256, + "internal": { + "total": 308083, + "free": 73443, + "allocated": 234640, + "largest_block": 31744 + }, + "psram": { + "total": 8370324, + "free": 7613996, + "allocated": 756328, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 749250 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/samples.jsonl b/docs/repair/ssh-poll-stack/device-candidate/samples.jsonl new file mode 100644 index 0000000..0861b09 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/samples.jsonl @@ -0,0 +1,368 @@ +{"time": "2026-09-28T18:10:49.960268", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1692, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1384, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673344, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 53548}}} +{"time": "2026-09-28T18:10:52.034617", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1692, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 55612}}} +{"time": "2026-09-28T18:10:54.098290", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1692, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673352, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 57670}}} +{"time": "2026-09-28T18:10:56.156293", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1692, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 59731}}} +{"time": "2026-09-28T18:10:58.214361", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1692, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 61789}}} +{"time": "2026-09-28T18:11:00.271306", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7666824, "min_free_heap": 7551012, "internal": {"total": 308143, "free": 73975, "allocated": 234168, "largest_block": 31744}, "psram": {"total": 8369732, "free": 7608388, "allocated": 761344, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 63850}}} +{"time": "2026-09-28T18:11:02.335874", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672580, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370340, "free": 7614056, "allocated": 756284, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 65923}}} +{"time": "2026-09-28T18:11:04.409353", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 67987}}} +{"time": "2026-09-28T18:11:06.471037", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 70050}}} +{"time": "2026-09-28T18:11:08.535534", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 72111}}} +{"time": "2026-09-28T18:11:10.595547", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 74171}}} +{"time": "2026-09-28T18:11:12.652458", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 76232}}} +{"time": "2026-09-28T18:11:14.718013", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672764, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370336, "free": 7614252, "allocated": 756084, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 78312}}} +{"time": "2026-09-28T18:11:16.796533", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 80372}}} +{"time": "2026-09-28T18:11:18.854249", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 82431}}} +{"time": "2026-09-28T18:11:20.914802", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 84493}}} +{"time": "2026-09-28T18:11:22.979305", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673352, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614824, "allocated": 755520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 86557}}} +{"time": "2026-09-28T18:11:25.039640", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1660, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1352, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7673348, "min_free_heap": 7551012, "internal": {"total": 308147, "free": 74039, "allocated": 234108, "largest_block": 31744}, "psram": {"total": 8370344, "free": 7614828, "allocated": 755516, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 88615}}} +{"time": "2026-09-28T18:11:27.097065", "tasks": {"code": 0, "data": {"tasks": [{"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "ready"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 5108, "core": 2147483647, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3808, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671200, "min_free_heap": 7551012, "internal": {"total": 308127, "free": 73523, "allocated": 234604, "largest_block": 31744}, "psram": {"total": 8370288, "free": 7613180, "allocated": 757108, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 93374}}} +{"time": "2026-09-28T18:11:31.858951", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 4772, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671120, "min_free_heap": 7550436, "internal": {"total": 308083, "free": 73119, "allocated": 234964, "largest_block": 31744}, "psram": {"total": 8370288, "free": 7613504, "allocated": 756784, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 95439}}} +{"time": "2026-09-28T18:11:33.923549", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2696, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670996, "min_free_heap": 7550256, "internal": {"total": 308071, "free": 72999, "allocated": 235072, "largest_block": 31744}, "psram": {"total": 8370288, "free": 7613492, "allocated": 756796, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 97503}}} +{"time": "2026-09-28T18:11:35.983897", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670756, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370284, "free": 7613300, "allocated": 756984, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 99563}}} +{"time": "2026-09-28T18:11:38.048411", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670756, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370284, "free": 7613316, "allocated": 756968, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 101621}}} +{"time": "2026-09-28T18:11:40.109784", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670756, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370284, "free": 7613296, "allocated": 756988, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 103684}}} +{"time": "2026-09-28T18:11:42.169759", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670756, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370284, "free": 7613304, "allocated": 756980, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 105744}}} +{"time": "2026-09-28T18:11:44.226229", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670756, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370284, "free": 7613316, "allocated": 756968, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 107804}}} +{"time": "2026-09-28T18:11:46.288887", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670756, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370284, "free": 7613300, "allocated": 756984, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 109866}}} +{"time": "2026-09-28T18:11:48.349018", "tasks": {"code": 0, "data": {"tasks": [{"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7669980, "min_free_heap": 7550256, "internal": {"total": 308067, "free": 72963, "allocated": 235104, "largest_block": 31744}, "psram": {"total": 8370280, "free": 7612524, "allocated": 757756, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 111939}}} +{"time": "2026-09-28T18:11:50.423444", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4288, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7598948, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370184, "free": 7542484, "allocated": 827700, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 114001}}} +{"time": "2026-09-28T18:11:52.486603", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7598948, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370184, "free": 7542476, "allocated": 827708, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 116061}}} +{"time": "2026-09-28T18:11:54.546025", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7599724, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370188, "free": 7543244, "allocated": 826944, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 118121}}} +{"time": "2026-09-28T18:11:56.605947", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7599724, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370188, "free": 7543232, "allocated": 826956, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 120184}}} +{"time": "2026-09-28T18:11:58.671577", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7599704, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370188, "free": 7543228, "allocated": 826960, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 122246}}} +{"time": "2026-09-28T18:12:00.731659", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7599716, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370188, "free": 7543240, "allocated": 826948, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 124306}}} +{"time": "2026-09-28T18:12:02.791320", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7599720, "min_free_heap": 7550256, "internal": {"total": 308019, "free": 71979, "allocated": 236040, "largest_block": 31744}, "psram": {"total": 8370188, "free": 7543240, "allocated": 826948, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 126372}}} +{"time": "2026-09-28T18:12:04.858803", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544400, "allocated": 825836, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 128431}}} +{"time": "2026-09-28T18:12:06.918265", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 130495}}} +{"time": "2026-09-28T18:12:08.980984", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 132552}}} +{"time": "2026-09-28T18:12:11.037088", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 134617}}} +{"time": "2026-09-28T18:12:13.101696", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 136676}}} +{"time": "2026-09-28T18:12:15.161926", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 138739}}} +{"time": "2026-09-28T18:12:17.224564", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 140804}}} +{"time": "2026-09-28T18:12:19.290058", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 142870}}} +{"time": "2026-09-28T18:12:21.351880", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544384, "allocated": 825852, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 144924}}} +{"time": "2026-09-28T18:12:23.420755", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 146999}}} +{"time": "2026-09-28T18:12:25.482284", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 149061}}} +{"time": "2026-09-28T18:12:27.544833", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544388, "allocated": 825848, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 151120}}} +{"time": "2026-09-28T18:12:29.607198", "tasks": {"code": 0, "data": {"tasks": [{"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601332, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544364, "allocated": 825872, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 153183}}} +{"time": "2026-09-28T18:12:31.664444", "tasks": {"code": 0, "data": {"tasks": [{"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "ready"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544400, "allocated": 825836, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 155237}}} +{"time": "2026-09-28T18:12:33.723986", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 157300}}} +{"time": "2026-09-28T18:12:35.785689", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544376, "allocated": 825860, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 159360}}} +{"time": "2026-09-28T18:12:37.847449", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 161429}}} +{"time": "2026-09-28T18:12:39.913988", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 163488}}} +{"time": "2026-09-28T18:12:41.974805", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 165547}}} +{"time": "2026-09-28T18:12:44.032713", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 167608}}} +{"time": "2026-09-28T18:12:46.093910", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601340, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544372, "allocated": 825864, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 169666}}} +{"time": "2026-09-28T18:12:48.151329", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 171725}}} +{"time": "2026-09-28T18:12:50.209378", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 173782}}} +{"time": "2026-09-28T18:12:52.267628", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 175844}}} +{"time": "2026-09-28T18:12:54.326772", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544376, "allocated": 825860, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 177899}}} +{"time": "2026-09-28T18:12:56.387017", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601352, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 179961}}} +{"time": "2026-09-28T18:12:58.443866", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600576, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7543632, "allocated": 826600, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 182021}}} +{"time": "2026-09-28T18:13:00.506686", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544388, "allocated": 825848, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 184082}}} +{"time": "2026-09-28T18:13:02.569592", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 186145}}} +{"time": "2026-09-28T18:13:04.633237", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544376, "allocated": 825860, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 188205}}} +{"time": "2026-09-28T18:13:06.690794", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601340, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544372, "allocated": 825864, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 190265}}} +{"time": "2026-09-28T18:13:08.751042", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544376, "allocated": 825860, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 192325}}} +{"time": "2026-09-28T18:13:10.812363", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 194386}}} +{"time": "2026-09-28T18:13:12.872002", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601336, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544372, "allocated": 825864, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 196444}}} +{"time": "2026-09-28T18:13:14.929368", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 198502}}} +{"time": "2026-09-28T18:13:16.989963", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 200567}}} +{"time": "2026-09-28T18:13:19.053220", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 202632}}} +{"time": "2026-09-28T18:13:21.115685", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 204695}}} +{"time": "2026-09-28T18:13:23.182506", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 206760}}} +{"time": "2026-09-28T18:13:25.246929", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 208824}}} +{"time": "2026-09-28T18:13:27.307829", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 210885}}} +{"time": "2026-09-28T18:13:29.367174", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 212943}}} +{"time": "2026-09-28T18:13:31.428964", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601348, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 215007}}} +{"time": "2026-09-28T18:13:33.502457", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600576, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7543632, "allocated": 826600, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 217078}}} +{"time": "2026-09-28T18:13:35.566099", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600576, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7543632, "allocated": 826600, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 219142}}} +{"time": "2026-09-28T18:13:37.627497", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 221206}}} +{"time": "2026-09-28T18:13:39.690706", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 223267}}} +{"time": "2026-09-28T18:13:41.753268", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601560, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544612, "allocated": 825628, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 225329}}} +{"time": "2026-09-28T18:13:43.813587", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 227388}}} +{"time": "2026-09-28T18:13:45.875011", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 229451}}} +{"time": "2026-09-28T18:13:47.938210", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 231515}}} +{"time": "2026-09-28T18:13:50.002244", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 233581}}} +{"time": "2026-09-28T18:13:52.067333", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 235647}}} +{"time": "2026-09-28T18:13:54.132487", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 237710}}} +{"time": "2026-09-28T18:13:56.197078", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 239773}}} +{"time": "2026-09-28T18:13:58.260192", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 241838}}} +{"time": "2026-09-28T18:14:00.325059", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544588, "allocated": 825652, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 243901}}} +{"time": "2026-09-28T18:14:02.383715", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 245959}}} +{"time": "2026-09-28T18:14:04.443762", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 248018}}} +{"time": "2026-09-28T18:14:06.504065", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600788, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7543844, "allocated": 826392, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 250082}}} +{"time": "2026-09-28T18:14:08.569026", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600780, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7543812, "allocated": 826424, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 252148}}} +{"time": "2026-09-28T18:14:10.642469", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600792, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7543844, "allocated": 826392, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 254220}}} +{"time": "2026-09-28T18:14:12.708729", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 256286}}} +{"time": "2026-09-28T18:14:14.770725", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 258348}}} +{"time": "2026-09-28T18:14:16.834953", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 260415}}} +{"time": "2026-09-28T18:14:18.901828", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 262479}}} +{"time": "2026-09-28T18:14:20.963959", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 264543}}} +{"time": "2026-09-28T18:14:23.031247", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 266607}}} +{"time": "2026-09-28T18:14:25.091220", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 268670}}} +{"time": "2026-09-28T18:14:27.157321", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 270732}}} +{"time": "2026-09-28T18:14:29.218898", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 272798}}} +{"time": "2026-09-28T18:14:31.283562", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 274862}}} +{"time": "2026-09-28T18:14:33.344800", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 276923}}} +{"time": "2026-09-28T18:14:35.411044", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 278984}}} +{"time": "2026-09-28T18:14:37.469883", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 281045}}} +{"time": "2026-09-28T18:14:39.531006", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601564, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544616, "allocated": 825624, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 283114}}} +{"time": "2026-09-28T18:14:41.603107", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600784, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7543828, "allocated": 826408, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 285183}}} +{"time": "2026-09-28T18:14:43.666651", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600788, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7543844, "allocated": 826392, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 287239}}} +{"time": "2026-09-28T18:14:45.724143", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671592, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7613644, "allocated": 756684, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 289305}}} +{"time": "2026-09-28T18:14:47.791781", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 291369}}} +{"time": "2026-09-28T18:14:49.855564", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 293431}}} +{"time": "2026-09-28T18:14:51.916196", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 295486}}} +{"time": "2026-09-28T18:14:53.972022", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 297549}}} +{"time": "2026-09-28T18:14:56.034160", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 299609}}} +{"time": "2026-09-28T18:14:58.095239", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672360, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 301666}}} +{"time": "2026-09-28T18:15:00.152606", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672360, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 303725}}} +{"time": "2026-09-28T18:15:02.211382", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 305789}}} +{"time": "2026-09-28T18:15:04.274676", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 307845}}} +{"time": "2026-09-28T18:15:06.331766", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672360, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 309905}}} +{"time": "2026-09-28T18:15:08.391491", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672368, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614436, "allocated": 755896, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 311963}}} +{"time": "2026-09-28T18:15:10.446647", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 314018}}} +{"time": "2026-09-28T18:15:12.504545", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 316075}}} +{"time": "2026-09-28T18:15:14.557240", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 318132}}} +{"time": "2026-09-28T18:15:16.632891", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672368, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 320210}}} +{"time": "2026-09-28T18:15:18.696398", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 322267}}} +{"time": "2026-09-28T18:15:20.754598", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 324324}}} +{"time": "2026-09-28T18:15:22.808623", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672368, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 326380}}} +{"time": "2026-09-28T18:15:24.867715", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672368, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 328439}}} +{"time": "2026-09-28T18:15:26.927359", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672368, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 330505}}} +{"time": "2026-09-28T18:15:28.992152", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672368, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614420, "allocated": 755912, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 332571}}} +{"time": "2026-09-28T18:15:31.056588", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672364, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370332, "free": 7614416, "allocated": 755916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 334636}}} +{"time": "2026-09-28T18:15:33.123046", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4300, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601552, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544584, "allocated": 825656, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 336695}}} +{"time": "2026-09-28T18:15:35.183530", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4108, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601552, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72447, "allocated": 235588, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544592, "allocated": 825648, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 338760}}} +{"time": "2026-09-28T18:15:37.247133", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4108, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601552, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72447, "allocated": 235588, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544592, "allocated": 825648, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 340825}}} +{"time": "2026-09-28T18:15:39.309907", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4108, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601552, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72447, "allocated": 235588, "largest_block": 31744}, "psram": {"total": 8370240, "free": 7544592, "allocated": 825648, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 342886}}} +{"time": "2026-09-28T18:15:41.374928", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614224, "allocated": 756104, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 344947}}} +{"time": "2026-09-28T18:15:43.435054", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614204, "allocated": 756124, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 347011}}} +{"time": "2026-09-28T18:15:45.497124", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614224, "allocated": 756104, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 349070}}} +{"time": "2026-09-28T18:15:47.557113", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614224, "allocated": 756104, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 351128}}} +{"time": "2026-09-28T18:15:49.614591", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614204, "allocated": 756124, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 353193}}} +{"time": "2026-09-28T18:15:51.677312", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671380, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613432, "allocated": 756892, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 355251}}} +{"time": "2026-09-28T18:15:53.737444", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614224, "allocated": 756104, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 357309}}} +{"time": "2026-09-28T18:15:55.794926", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614204, "allocated": 756124, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 359367}}} +{"time": "2026-09-28T18:15:57.854186", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614216, "allocated": 756112, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 361437}}} +{"time": "2026-09-28T18:15:59.921856", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614208, "allocated": 756120, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 363494}}} +{"time": "2026-09-28T18:16:01.983053", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614204, "allocated": 756124, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 365555}}} +{"time": "2026-09-28T18:16:04.042187", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614208, "allocated": 756120, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 367613}}} +{"time": "2026-09-28T18:16:06.099990", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614204, "allocated": 756124, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 369673}}} +{"time": "2026-09-28T18:16:08.159510", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614208, "allocated": 756120, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 371732}}} +{"time": "2026-09-28T18:16:10.215713", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614208, "allocated": 756120, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 373785}}} +{"time": "2026-09-28T18:16:12.271379", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614204, "allocated": 756124, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 375841}}} +{"time": "2026-09-28T18:16:14.326278", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4288, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601372, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544408, "allocated": 825828, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 378720}}} +{"time": "2026-09-28T18:16:17.206372", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601368, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 380783}}} +{"time": "2026-09-28T18:16:19.267735", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601368, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544404, "allocated": 825832, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 382846}}} +{"time": "2026-09-28T18:16:21.330662", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 384907}}} +{"time": "2026-09-28T18:16:23.393184", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 386965}}} +{"time": "2026-09-28T18:16:25.448667", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 389018}}} +{"time": "2026-09-28T18:16:27.505227", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 391078}}} +{"time": "2026-09-28T18:16:29.564303", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 393140}}} +{"time": "2026-09-28T18:16:31.623398", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 395200}}} +{"time": "2026-09-28T18:16:33.686701", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671160, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613228, "allocated": 757092, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 397267}}} +{"time": "2026-09-28T18:16:35.749714", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671156, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613224, "allocated": 757096, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 399323}}} +{"time": "2026-09-28T18:16:37.808195", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671172, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613240, "allocated": 757080, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 401382}}} +{"time": "2026-09-28T18:16:39.869681", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613988, "allocated": 756336, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 403446}}} +{"time": "2026-09-28T18:16:41.933072", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671932, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 405506}}} +{"time": "2026-09-28T18:16:43.993227", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 407565}}} +{"time": "2026-09-28T18:16:46.054251", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 409629}}} +{"time": "2026-09-28T18:16:48.113211", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 411683}}} +{"time": "2026-09-28T18:16:50.169709", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 413739}}} +{"time": "2026-09-28T18:16:52.226147", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 415798}}} +{"time": "2026-09-28T18:16:54.286992", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 417860}}} +{"time": "2026-09-28T18:16:56.345654", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 419919}}} +{"time": "2026-09-28T18:16:58.403676", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 421978}}} +{"time": "2026-09-28T18:17:00.467631", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 424044}}} +{"time": "2026-09-28T18:17:02.531791", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 426108}}} +{"time": "2026-09-28T18:17:04.595757", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 428171}}} +{"time": "2026-09-28T18:17:06.657279", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 430229}}} +{"time": "2026-09-28T18:17:08.717470", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613160, "allocated": 757160, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 432300}}} +{"time": "2026-09-28T18:17:10.785388", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671172, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613236, "allocated": 757084, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 434368}}} +{"time": "2026-09-28T18:17:12.855793", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4288, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7599472, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370228, "free": 7542756, "allocated": 827472, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 436439}}} +{"time": "2026-09-28T18:17:14.924425", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600984, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370224, "free": 7544012, "allocated": 826212, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 438508}}} +{"time": "2026-09-28T18:17:16.997084", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601148, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544164, "allocated": 826068, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 440575}}} +{"time": "2026-09-28T18:17:19.062827", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 442635}}} +{"time": "2026-09-28T18:17:21.122856", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 444694}}} +{"time": "2026-09-28T18:17:23.180242", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 446758}}} +{"time": "2026-09-28T18:17:25.245739", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 448816}}} +{"time": "2026-09-28T18:17:27.302832", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 450879}}} +{"time": "2026-09-28T18:17:29.364552", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 452936}}} +{"time": "2026-09-28T18:17:31.425550", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 455003}}} +{"time": "2026-09-28T18:17:33.484850", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 457055}}} +{"time": "2026-09-28T18:17:35.542623", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 459116}}} +{"time": "2026-09-28T18:17:37.603456", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 461178}}} +{"time": "2026-09-28T18:17:39.664966", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 463235}}} +{"time": "2026-09-28T18:17:41.722189", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 465296}}} +{"time": "2026-09-28T18:17:43.784016", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 467359}}} +{"time": "2026-09-28T18:17:45.846830", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 469423}}} +{"time": "2026-09-28T18:17:47.912128", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 471486}}} +{"time": "2026-09-28T18:17:49.973621", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 473542}}} +{"time": "2026-09-28T18:17:52.031399", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 475603}}} +{"time": "2026-09-28T18:17:54.090271", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 477665}}} +{"time": "2026-09-28T18:17:56.152624", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 479721}}} +{"time": "2026-09-28T18:17:58.208624", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 481783}}} +{"time": "2026-09-28T18:18:00.270448", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 483842}}} +{"time": "2026-09-28T18:18:02.328945", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 485906}}} +{"time": "2026-09-28T18:18:04.394337", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 487970}}} +{"time": "2026-09-28T18:18:06.458231", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 490033}}} +{"time": "2026-09-28T18:18:08.518330", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 492092}}} +{"time": "2026-09-28T18:18:10.581616", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 494153}}} +{"time": "2026-09-28T18:18:12.636092", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614008, "allocated": 756316, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 496209}}} +{"time": "2026-09-28T18:18:14.697036", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 498271}}} +{"time": "2026-09-28T18:18:16.759615", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 500335}}} +{"time": "2026-09-28T18:18:18.822245", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671168, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613220, "allocated": 757100, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 502404}}} +{"time": "2026-09-28T18:18:20.888626", "tasks": {"code": 0, "data": {"tasks": [{"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7672152, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370328, "free": 7614216, "allocated": 756112, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 504461}}} +{"time": "2026-09-28T18:18:22.949203", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4544, "core": 2147483647, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601332, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72459, "allocated": 235576, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544288, "allocated": 825944, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 506741}}} +{"time": "2026-09-28T18:18:25.225149", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601332, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72447, "allocated": 235588, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544380, "allocated": 825856, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 508802}}} +{"time": "2026-09-28T18:18:27.288557", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601324, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72447, "allocated": 235588, "largest_block": 31744}, "psram": {"total": 8370236, "free": 7544364, "allocated": 825872, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 510863}}} +{"time": "2026-09-28T18:18:29.350912", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 512925}}} +{"time": "2026-09-28T18:18:31.409663", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 514985}}} +{"time": "2026-09-28T18:18:33.472960", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 517044}}} +{"time": "2026-09-28T18:18:35.530833", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 519101}}} +{"time": "2026-09-28T18:18:37.588815", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 521162}}} +{"time": "2026-09-28T18:18:39.650711", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 523223}}} +{"time": "2026-09-28T18:18:41.710616", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613988, "allocated": 756336, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 525282}}} +{"time": "2026-09-28T18:18:43.766974", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 527343}}} +{"time": "2026-09-28T18:18:45.830585", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 529411}}} +{"time": "2026-09-28T18:18:47.899413", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671168, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613220, "allocated": 757100, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 531481}}} +{"time": "2026-09-28T18:18:49.964245", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 533539}}} +{"time": "2026-09-28T18:18:52.026308", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 535602}}} +{"time": "2026-09-28T18:18:54.088292", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 537666}}} +{"time": "2026-09-28T18:18:56.156708", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 539728}}} +{"time": "2026-09-28T18:18:58.213957", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 541785}}} +{"time": "2026-09-28T18:19:00.272451", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 543850}}} +{"time": "2026-09-28T18:19:02.337987", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4300, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601152, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544172, "allocated": 826060, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 545913}}} +{"time": "2026-09-28T18:19:04.397763", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4108, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601148, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544168, "allocated": 826064, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 547971}}} +{"time": "2026-09-28T18:19:06.458867", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4108, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601156, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544176, "allocated": 826056, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 550035}}} +{"time": "2026-09-28T18:19:08.524424", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613796, "allocated": 756524, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 552093}}} +{"time": "2026-09-28T18:19:10.579111", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 554150}}} +{"time": "2026-09-28T18:19:12.639518", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 556215}}} +{"time": "2026-09-28T18:19:14.703401", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 558273}}} +{"time": "2026-09-28T18:19:16.760595", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 560336}}} +{"time": "2026-09-28T18:19:18.823678", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 562394}}} +{"time": "2026-09-28T18:19:20.883232", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671096, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613164, "allocated": 757156, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 564466}}} +{"time": "2026-09-28T18:19:22.950400", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671172, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613240, "allocated": 757080, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 566523}}} +{"time": "2026-09-28T18:19:25.011011", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671172, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613236, "allocated": 757084, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 568585}}} +{"time": "2026-09-28T18:19:27.074655", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 570648}}} +{"time": "2026-09-28T18:19:29.135361", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 572708}}} +{"time": "2026-09-28T18:19:31.195399", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 574766}}} +{"time": "2026-09-28T18:19:33.253710", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 576826}}} +{"time": "2026-09-28T18:19:35.313323", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 578881}}} +{"time": "2026-09-28T18:19:37.369310", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 580939}}} +{"time": "2026-09-28T18:19:39.426531", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 582998}}} +{"time": "2026-09-28T18:19:41.486618", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 585060}}} +{"time": "2026-09-28T18:19:43.547754", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 587124}}} +{"time": "2026-09-28T18:19:45.612236", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 589189}}} +{"time": "2026-09-28T18:19:47.677772", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 591255}}} +{"time": "2026-09-28T18:19:49.738317", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 593316}}} +{"time": "2026-09-28T18:19:51.804554", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 595375}}} +{"time": "2026-09-28T18:19:53.863282", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 597440}}} +{"time": "2026-09-28T18:19:55.928364", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4288, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600244, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370228, "free": 7543312, "allocated": 826916, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 599514}}} +{"time": "2026-09-28T18:19:57.999845", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600356, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370228, "free": 7543388, "allocated": 826840, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 601575}}} +{"time": "2026-09-28T18:20:00.061702", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600356, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370228, "free": 7543388, "allocated": 826840, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 603640}}} +{"time": "2026-09-28T18:20:02.128598", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601128, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544160, "allocated": 826072, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 605713}}} +{"time": "2026-09-28T18:20:04.201642", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613792, "allocated": 756528, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 607777}}} +{"time": "2026-09-28T18:20:06.264948", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 609836}}} +{"time": "2026-09-28T18:20:08.323903", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 611899}}} +{"time": "2026-09-28T18:20:10.387499", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 613957}}} +{"time": "2026-09-28T18:20:12.446976", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 616021}}} +{"time": "2026-09-28T18:20:14.507333", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 618079}}} +{"time": "2026-09-28T18:20:16.567413", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 620138}}} +{"time": "2026-09-28T18:20:18.627178", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 622199}}} +{"time": "2026-09-28T18:20:20.687115", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 624263}}} +{"time": "2026-09-28T18:20:22.750349", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 626327}}} +{"time": "2026-09-28T18:20:24.813037", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 628387}}} +{"time": "2026-09-28T18:20:26.874658", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 630445}}} +{"time": "2026-09-28T18:20:28.929406", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 632501}}} +{"time": "2026-09-28T18:20:30.989770", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 634572}}} +{"time": "2026-09-28T18:20:33.059739", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 636629}}} +{"time": "2026-09-28T18:20:35.119325", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 638699}}} +{"time": "2026-09-28T18:20:37.185283", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 640762}}} +{"time": "2026-09-28T18:20:39.246867", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 642821}}} +{"time": "2026-09-28T18:20:41.307478", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 644883}}} +{"time": "2026-09-28T18:20:43.372248", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 646946}}} +{"time": "2026-09-28T18:20:45.434335", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 649010}}} +{"time": "2026-09-28T18:20:47.498809", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4288, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601148, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72471, "allocated": 235564, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544180, "allocated": 826052, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 651753}}} +{"time": "2026-09-28T18:20:50.238406", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601148, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72471, "allocated": 235564, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544180, "allocated": 826052, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 653813}}} +{"time": "2026-09-28T18:20:52.300105", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601152, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72471, "allocated": 235564, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544184, "allocated": 826048, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 655878}}} +{"time": "2026-09-28T18:20:54.367041", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601148, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72471, "allocated": 235564, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544180, "allocated": 826052, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 657944}}} +{"time": "2026-09-28T18:20:56.434721", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 660009}}} +{"time": "2026-09-28T18:20:58.494414", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 662071}}} +{"time": "2026-09-28T18:21:00.558727", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671716, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 664131}}} +{"time": "2026-09-28T18:21:02.619219", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 666193}}} +{"time": "2026-09-28T18:21:04.681630", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 668251}}} +{"time": "2026-09-28T18:21:06.739671", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 670313}}} +{"time": "2026-09-28T18:21:08.799408", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 672369}}} +{"time": "2026-09-28T18:21:10.857113", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 674428}}} +{"time": "2026-09-28T18:21:12.916054", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 676486}}} +{"time": "2026-09-28T18:21:14.971773", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 678544}}} +{"time": "2026-09-28T18:21:17.032766", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613140, "allocated": 757180, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 680613}}} +{"time": "2026-09-28T18:21:19.101284", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671928, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 682676}}} +{"time": "2026-09-28T18:21:21.164182", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1596, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671312, "min_free_heap": 7550256, "internal": {"total": 308079, "free": 73323, "allocated": 234756, "largest_block": 31744}, "psram": {"total": 8370304, "free": 7613492, "allocated": 756812, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 684762}}} +{"time": "2026-09-28T18:21:23.250196", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 686821}}} +{"time": "2026-09-28T18:21:25.307727", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671936, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 688876}}} +{"time": "2026-09-28T18:21:27.363083", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 690935}}} +{"time": "2026-09-28T18:21:29.423819", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 692996}}} +{"time": "2026-09-28T18:21:31.484275", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 695053}}} +{"time": "2026-09-28T18:21:33.541844", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 697118}}} +{"time": "2026-09-28T18:21:35.607433", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 699184}}} +{"time": "2026-09-28T18:21:37.673375", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 701248}}} +{"time": "2026-09-28T18:21:39.737468", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 703313}}} +{"time": "2026-09-28T18:21:41.801684", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 705373}}} +{"time": "2026-09-28T18:21:43.861492", "tasks": {"code": 0, "data": {"tasks": [{"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614004, "allocated": 756320, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 707435}}} +{"time": "2026-09-28T18:21:45.923862", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671916, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613988, "allocated": 756336, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 709492}}} +{"time": "2026-09-28T18:21:47.978354", "tasks": {"code": 0, "data": {"tasks": [{"name": "ssh_poll", "priority": 5, "stack_hwm": 4288, "core": 2147483647, "state": "ready"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601136, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72463, "allocated": 235572, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544172, "allocated": 826060, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 712500}}} +{"time": "2026-09-28T18:21:50.988734", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601152, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72463, "allocated": 235572, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544188, "allocated": 826044, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 714561}}} +{"time": "2026-09-28T18:21:53.046664", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4096, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601140, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72463, "allocated": 235572, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544176, "allocated": 826056, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 716625}}} +{"time": "2026-09-28T18:21:55.112330", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3952, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600380, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72463, "allocated": 235572, "largest_block": 31744}, "psram": {"total": 8370228, "free": 7543416, "allocated": 826812, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 718695}}} +{"time": "2026-09-28T18:21:57.183979", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3952, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7600380, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72463, "allocated": 235572, "largest_block": 31744}, "psram": {"total": 8370228, "free": 7543416, "allocated": 826812, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 720761}}} +{"time": "2026-09-28T18:21:59.250160", "tasks": {"code": 0, "data": {"tasks": [{"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613792, "allocated": 756528, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 722821}}} +{"time": "2026-09-28T18:22:01.306354", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671728, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613780, "allocated": 756540, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 724883}}} +{"time": "2026-09-28T18:22:03.372168", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 726941}}} +{"time": "2026-09-28T18:22:05.430999", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 728999}}} +{"time": "2026-09-28T18:22:07.484228", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 731053}}} +{"time": "2026-09-28T18:22:09.541793", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 733110}}} +{"time": "2026-09-28T18:22:11.598388", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 735171}}} +{"time": "2026-09-28T18:22:13.661635", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 737232}}} +{"time": "2026-09-28T18:22:15.720915", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 739294}}} +{"time": "2026-09-28T18:22:17.787756", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 741365}}} +{"time": "2026-09-28T18:22:19.851501", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 743427}}} +{"time": "2026-09-28T18:22:21.915320", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613996, "allocated": 756328, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 745489}}} +{"time": "2026-09-28T18:22:23.975982", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 747551}}} +{"time": "2026-09-28T18:22:26.037378", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 749609}}} +{"time": "2026-09-28T18:22:28.097520", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614012, "allocated": 756312, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 751667}}} +{"time": "2026-09-28T18:22:30.157977", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671168, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613224, "allocated": 757096, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 753732}}} +{"time": "2026-09-28T18:22:32.220794", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671172, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613240, "allocated": 757080, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 755790}}} +{"time": "2026-09-28T18:22:34.279182", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614000, "allocated": 756324, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 757852}}} +{"time": "2026-09-28T18:22:36.340642", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671944, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613144, "allocated": 757176, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 759921}}} +{"time": "2026-09-28T18:22:38.405941", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4292, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601156, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544180, "allocated": 826052, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 761982}}} +{"time": "2026-09-28T18:22:40.469624", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4100, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601156, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544180, "allocated": 826052, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 764046}}} +{"time": "2026-09-28T18:22:42.535996", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4100, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601156, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544184, "allocated": 826048, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 766112}}} +{"time": "2026-09-28T18:22:44.600810", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3876, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7601156, "min_free_heap": 7550256, "internal": {"total": 308035, "free": 72467, "allocated": 235568, "largest_block": 31744}, "psram": {"total": 8370232, "free": 7544184, "allocated": 826048, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 768179}}} +{"time": "2026-09-28T18:22:46.668416", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 770238}}} +{"time": "2026-09-28T18:22:48.728069", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671716, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613784, "allocated": 756536, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 772297}}} +{"time": "2026-09-28T18:22:50.785501", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 774356}}} +{"time": "2026-09-28T18:22:52.846205", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671732, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370320, "free": 7613800, "allocated": 756520, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 776414}}} +{"time": "2026-09-28T18:22:54.902470", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7614004, "allocated": 756320, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 778474}}} +{"time": "2026-09-28T18:22:56.962672", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 780534}}} +{"time": "2026-09-28T18:22:59.020063", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 782589}}} +{"time": "2026-09-28T18:23:01.077329", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 784652}}} +{"time": "2026-09-28T18:23:03.138384", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671940, "min_free_heap": 7550256, "internal": {"total": 308083, "free": 73443, "allocated": 234640, "largest_block": 31744}, "psram": {"total": 8370324, "free": 7613992, "allocated": 756332, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 786708}}} +{"time": "2026-09-28T18:23:05.196876", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670648, "min_free_heap": 7550256, "internal": {"total": 308087, "free": 73479, "allocated": 234608, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7612676, "allocated": 757636, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 788861}}} +{"time": "2026-09-28T18:23:07.350799", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1108, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2680, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7670800, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370308, "free": 7612948, "allocated": 757360, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 790923}}} +{"time": "2026-09-28T18:23:09.411797", "tasks": {"code": 0, "data": {"tasks": [{"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671576, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613736, "allocated": 756576, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 792985}}} +{"time": "2026-09-28T18:23:11.474132", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671576, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613736, "allocated": 756576, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 795047}}} +{"time": "2026-09-28T18:23:13.533489", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671576, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613736, "allocated": 756576, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 797103}}} +{"time": "2026-09-28T18:23:15.592494", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671572, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613736, "allocated": 756576, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 799164}}} +{"time": "2026-09-28T18:23:17.651456", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671572, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613736, "allocated": 756576, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 801220}}} +{"time": "2026-09-28T18:23:19.709071", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671572, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613732, "allocated": 756580, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 803281}}} +{"time": "2026-09-28T18:23:21.769658", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7671572, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370312, "free": 7613736, "allocated": 756576, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 805349}}} +{"time": "2026-09-28T18:23:23.838239", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7636276, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8369984, "free": 7578440, "allocated": 791544, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 807412}}} +{"time": "2026-09-28T18:23:25.902953", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7633728, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8369640, "free": 7575880, "allocated": 793760, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 809479}}} +{"time": "2026-09-28T18:23:27.970467", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7637996, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8370212, "free": 7580160, "allocated": 790052, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 811544}}} +{"time": "2026-09-28T18:23:30.032385", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7635340, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8369852, "free": 7577496, "allocated": 792356, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 813607}}} +{"time": "2026-09-28T18:23:32.096738", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 1060, "core": 1, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1364, "core": 0, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 688, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 696, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 2032, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1564, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1956, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1792, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 1336, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 908, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 13008, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2792, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5432, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 392, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 2160, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15124, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1964, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 496, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 900, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 904, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2504, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1684, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 392, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 800, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7635328, "min_free_heap": 7549148, "internal": {"total": 308083, "free": 73359, "allocated": 234724, "largest_block": 31744}, "psram": {"total": 8369852, "free": 7577472, "allocated": 792380, "largest_block": 7471104}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:01:50", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 815667}}} diff --git a/docs/repair/ssh-poll-stack/device-candidate/serial-redacted.log b/docs/repair/ssh-poll-stack/device-candidate/serial-redacted.log new file mode 100644 index 0000000..d7446fe --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/serial-redacted.log @@ -0,0 +1,749 @@ +ESP-ROM:esp32s3-20210327 +Build:Mar 27 2021 +rst:0x15 (USB_UART_CHIP_RESET),boot:0x8 (SPI_FAST_FLASH_BOOT) +Saved PC:0x4037a8b6 +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3fce2820,len:0x1700 +load:0x403c8700,len:0xec0 +load:0x403cb700,len:0x31c0 +entry 0x403c894c +I (24) boot: ESP-IDF v5.5.2 2nd stage bootloader +I (24) boot: compile time Sep 28 2026 18:02:01 +I (25) boot: Multicore bootloader +I (25) boot: chip revision: v0.2 +I (27) boot: efuse block revision: v1.3 +I (31) qio_mode: Enabling default flash chip QIO +I (35) boot.esp32s3: Boot SPI Speed : 80MHz +I (39) boot.esp32s3: SPI Mode : QIO +I (43) boot.esp32s3: SPI Flash Size : 16MB +I (47) boot: Enabling RNG early entropy source... +I (51) boot: Partition Table: +I (54) boot: ## Label Usage Type ST Offset Length +I (60) boot: 0 nvs WiFi data 01 02 00009000 0000c000 +I (67) boot: 1 nvs_keys NVS keys 01 04 00015000 00001000 +I (73) boot: 2 otadata OTA data 01 00 00016000 00002000 +I (80) boot: 3 phy_init RF data 01 01 00018000 00001000 +I (86) boot: 4 ota_0 OTA app 00 10 00020000 00300000 +I (93) boot: 5 ota_1 OTA app 00 11 00320000 00300000 +I (99) boot: 6 storage Unknown data 01 82 00620000 00080000 +I (106) boot: 7 www Unknown data 01 82 006a0000 00300000 +I (112) boot: 8 fatfs Unknown data 01 81 009a0000 00010000 +I (119) boot: End of partition table +I (123) esp_image: segment 0: paddr=00020020 vaddr=3c170020 size=97008h (618504) map +I (222) esp_image: segment 1: paddr=000b7030 vaddr=3fc9bf00 size=04efch ( 20220) load +I (226) esp_image: segment 2: paddr=000bbf34 vaddr=40374000 size=040e4h ( 16612) load +I (229) esp_image: segment 3: paddr=000c0020 vaddr=42000020 size=1612dch (1446620) map +I (448) esp_image: segment 4: paddr=00221304 vaddr=403780e4 size=13dc4h ( 81348) load +I (464) esp_image: segment 5: paddr=002350d0 vaddr=50000000 size=00020h ( 32) load +I (473) boot: Loaded app from partition at offset 0x20000 +I (474) boot: Disabling RNG early entropy source... +I (484) octal_psram: vendor id : 0x0d (AP) +I (484) octal_psram: dev id : 0x02 (generation 3) +I (484) octal_psram: density : 0x03 (64 Mbit) +I (486) octal_psram: good-die : 0x01 (Pass) +I (490) octal_psram: Latency : 0x01 (Fixed) +I (495) octal_psram: VCC : 0x01 (3V) +I (499) octal_psram: SRF : 0x01 (Fast Refresh) +I (504) octal_psram: BurstType : 0x01 (Hybrid Wrap) +I (509) octal_psram: BurstLen : 0x01 (32 Byte) +I (513) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) +I (518) octal_psram: DriveStrength: 0x00 (1/1) +I (523) MSPI Timing: Enter psram timing tuning +I (527) esp_psram: Found 8MB PSRAM device +I (530) esp_psram: Speed: 80MHz +I (533) cpu_start: Multicore app +I (969) esp_psram: SPI SRAM memory test OK +I (978) cpu_start: GPIO 44 and 43 are used as console UART I/O pins +I (978) cpu_start: Pro cpu start user code +I (978) cpu_start: cpu freq: 240000000 Hz +I (980) app_init: Application information: +I (984) app_init: Project name: TianShanOS +I (988) app_init: App version: 0.5.2+3a19128d.09281801 +I (993) app_init: Compile time: Sep 28 2026 18:01:50 +I (998) app_init: ELF file SHA256: 2c29402b1... +I (1003) app_init: ESP-IDF: v5.5.2 +I (1007) efuse_init: Min chip rev: v0.0 +I (1011) efuse_init: Max chip rev: v0.99 +I (1015) efuse_init: Chip rev: v0.2 +I (1019) heap_init: Initializing. RAM available for dynamic allocation: +I (1025) heap_init: At 3FCB0048 len 000396C8 (229 KiB): RAM +I (1030) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM +I (1035) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM +I (1041) heap_init: At 600FE000 len 00001FE8 (7 KiB): RTCRAM +I (1046) esp_psram: Adding pool of 8179K of PSRAM memory to heap allocator +I (1053) spi_flash: detected chip: generic +I (1056) spi_flash: flash io: qio +I (1060) sleep_gpio: Configure to isolate all GPIO pins in sleep state +I (1066) sleep_gpio: Enable automatic switching of GPIO sleep configuration +I (1073) main_task: Started on CPU0 +I (1076) esp_psram: Reserving pool of 16K of internal memory for DMA/internal allocations +I (1084) main_task: Calling app_main() + +╔════════════════════════════════════════════════════════════════════════╗ +║ ║ +║ ████████╗██╗ █████╗ ███╗ ██╗███████╗██╗ ██╗ █████╗ ███╗ ██╗ ║ +║ ╚══██╔══╝██║██╔══██╗████╗ ██║██╔════╝██║ ██║██╔══██╗████╗ ██║ ║ +║ ██║ ██║███████║██╔██╗ ██║███████╗███████║███████║██╔██╗ ██║ ║ +║ ██║ ██║██╔══██║██║╚██╗██║╚════██║██╔══██║██╔══██║██║╚██╗██║ ║ +║ ██║ ██║██║ ██║██║ ╚████║███████║██║ ██║██║ ██║██║ ╚████║ ║ +║ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ║ +║ ║ +║ TianShanOS 0.5.2+3a19128d.09281801 ║ +║ ESP32 Rack Management Operating System ║ +║ ║ +╚════════════════════════════════════════════════════════════════════════╝ + +I (1259) main: System Information: +I (1262) main: - IDF Version: v5.5.2 +I (1265) main: - Free Heap: 8630188 bytes +I (1269) main: - Min Free Heap: 8630188 bytes +I (1274) main: - Chip: ESP32-S3, 2 cores, WiFi/BLE +I (1278) main: Initializing TianShanOS... +I (1282) ts_core: TianShanOS Core v0.5.2+3a19128d.09281801 initializing... +I (1289) ts_mempool: Initializing memory pools in PSRAM... +I (1294) ts_mempool: Pool 0: 16 x 256 bytes = 4 KB (PSRAM) +I (1299) ts_mempool: Pool 1: 12 x 1024 bytes = 12 KB (PSRAM) +I (1304) ts_mempool: Pool 2: 8 x 4096 bytes = 32 KB (PSRAM) +I (1310) ts_mempool: Pool 3: 4 x 8192 bytes = 32 KB (PSRAM) +I (1315) ts_mempool: Memory pools initialized successfully +I (1320) ts_core: Memory pools initialized in PSRAM +I (1325) ts_core: cJSON PSRAM hooks installed +I (1329) ts_core: Initializing configuration system... +I (1334) ts_config: Initializing TianShanOS Configuration System... +I (1340) ts_config: Configuration system initialized successfully +I (1346) ts_config_nvs: Initializing NVS configuration backend... +I (1401) ts_config_nvs: NVS backend initialized (namespace: ts_config) +I (1402) ts_config: Registered backend 1 with priority 80 +I (1402) ts_config_file: Initializing file configuration backend... +I (1408) ts_config_file: File backend initialized (waiting for storage) +I (1414) ts_config: Registered backend 2 with priority 60 +I (1419) ts_core: Initializing logging system... +I (1424) ts_log: Initializing TianShanOS Logging System... +I (1434) ts_log: Log buffer allocated in PSRAM (500 entries, 148000 bytes) +I (1438) ts_log: ESP_LOG capture hook installed +I (1443) ts_log: Logging system initialized (level=3, outputs=0x05, buffer=500) +I (1451) ts_core: Initializing event system... +I (1455) ts_event: Initializing TianShanOS Event System... +I (1460) ts_event: Event loop task started +I (1464) ts_event: Event system initialized (queue_size=32) +I (1469) ts_config_file: Registered storage event handler for auto-load +I (1476) ts_config_schemas: Initializing configuration module system... +I (1482) ts_config_module: Initializing configuration module system... +I (1488) ts_config_meta: Initializing configuration meta management... +I (1496) ts_config_meta: Meta initialized: global_seq=6, sync_seq=6, pending=0x00 +I (1502) ts_config_module: Configuration module system initialized +I (1508) ts_config_schemas: Registering configuration modules... +I (1513) ts_config_module: Registered module NET (nvs=ts_net, schema_v=1) +I (1520) ts_config_module: Registered module DHCP (nvs=ts_dhcp, schema_v=1) +I (1526) ts_config_module: Registered module WIFI (nvs=ts_wifi, schema_v=1) +I (1533) ts_config_module: Registered module NAT (nvs=ts_nat, schema_v=1) +I (1540) ts_config_module: Registered module LED (nvs=ts_led, schema_v=1) +I (1546) ts_config_module: Registered module FAN (nvs=ts_fan, schema_v=1) +I (1553) ts_config_module: Registered module DEVICE (nvs=ts_device, schema_v=1) +I (1560) ts_config_module: Registered module SYSTEM (nvs=ts_system, schema_v=1) +I (1567) ts_config_module: Registered module TEMP (nvs=ts_temp, schema_v=0) +I (1573) ts_config_module: Registered module RULES (nvs=ts_rules, schema_v=0) +I (1580) ts_config_module: Registered module ACTIONS (nvs=ts_actions, schema_v=0) +I (1588) ts_config_module: Registered module SOURCES (nvs=ts_sources, schema_v=0) +I (1595) ts_config_schemas: All configuration modules registered +I (1600) ts_config_schemas: Loading module configurations... +I (1606) ts_config_module: Loading module NET... +I (1610) ts_config_module: Using schema defaults for module NET +I (1616) ts_config_module: Loading module DHCP... +I (1620) ts_config_module: Using schema defaults for module DHCP +I (1626) ts_config_module: Loading module WIFI... +I (1630) ts_config_module: Using schema defaults for module WIFI +I (1636) ts_config_module: Loading module NAT... +I (1640) ts_config_module: Using schema defaults for module NAT +I (1646) ts_config_module: Loading module LED... +I (1650) ts_config_module: Using schema defaults for module LED +I (1656) ts_config_module: Loading module FAN... +I (1662) ts_config_module: Loading module DEVICE... +I (1665) ts_config_module: Using schema defaults for module DEVICE +I (1671) ts_config_module: Loading module SYSTEM... +I (1675) ts_config_module: Using schema defaults for module SYSTEM +I (1682) ts_config_module: Loading module TEMP... +I (1686) ts_config_module: Loading module RULES... +I (1690) ts_config_module: Using schema defaults for module RULES +I (1696) ts_config_module: Loading module ACTIONS... +I (1701) ts_config_module: Using schema defaults for module ACTIONS +I (1707) ts_config_module: Loading module SOURCES... +I (1711) ts_config_module: Using schema defaults for module SOURCES +I (1718) ts_config_meta: === Configuration Meta === +I (1722) ts_config_meta: global_seq: 6 +I (1726) ts_config_meta: sync_seq: 6 +I (1730) ts_config_meta: pending_sync: 0x00 +I (1734) ts_config_meta: Schema versions: +I (1738) ts_config_meta: ========================== +I (1742) ts_config_schemas: Configuration module system initialized +I (1748) ts_core: Initializing service management... +I (1753) ts_service: Initializing TianShanOS Service Management... +I (1759) ts_service: Service management initialized +I (1763) ts_core: TianShanOS Core initialized successfully +I (1769) main: Registering core services... +I (1773) ts_services: Registering services... +I (1777) ts_service: Registered service: hal (phase=HAL) +I (1782) ts_services: - hal service registered +I (1786) ts_service: Registered service: storage (phase=DRIVER) +I (1792) ts_services: - storage service registered +I (1796) ts_service: Registered service: led (phase=DRIVER) +I (1802) ts_services: - led service registered +I (1806) ts_service: Registered service: drivers (phase=DRIVER) +I (1812) ts_services: - drivers service registered +I (1816) ts_service: Registered service: power (phase=DRIVER) +I (1822) ts_services: - power service registered +I (1826) ts_service: Registered service: network (phase=NETWORK) +I (1832) ts_services: - network service registered +I (1837) ts_service: Registered service: security (phase=SECURITY) +I (1843) ts_services: - security service registered +I (1847) ts_service: Registered service: api (phase=SERVICE) +I (1853) ts_services: - api service registered +I (1857) ts_service: Registered service: https (phase=SERVICE) +I (1863) ts_services: - https service registered +I (1867) ts_service: Registered service: webui (phase=UI) +I (1872) ts_services: - webui service registered +I (1877) ts_service: Registered service: console (phase=UI) +I (1882) ts_services: - console service registered +I (1887) ts_service: Registered service: automation (phase=SERVICE) +I (1893) ts_services: - automation service registered +I (1898) ts_services: All core services registered +I (1902) main: Starting TianShanOS services... +I (1906) ts_core: Starting TianShanOS... +I (1910) ts_service: Starting all services... +I (1914) ts_service: === Phase 0: PLATFORM === +I (1918) ts_service: === Phase 1: CORE === +I (1922) ts_service: === Phase 2: HAL === +I (1926) ts_service: Starting 1 services in phase HAL +I (1931) ts_service: Starting service: hal +I (1934) ts_services: Initializing HAL service... +I (892) ts_hal: Initializing HAL module v1.0.0 +I (897) ts_pin: Initializing pin manager +I (902) ts_pin: Pin manager initialized +I (906) ts_hal: No pin config in NVS, loading defaults +I (912) ts_pin: Loading default pin mappings for ESP32S3 +I (918) ts_gpio: Initializing GPIO subsystem +I (923) ts_hal: Early hardware init: setting reset pins to safe state +I (930) ts_hal: W5500_RST (GPIO39) = HIGH (normal) +I (936) ts_hal: AGX_RESET (GPIO1) = LOW (normal) +I (941) ts_hal: AGX_POWER (GPIO3) = LOW (allow boot) +I (947) ts_pwm: Initializing PWM subsystem +I (951) ts_i2c: Initializing I2C subsystem +I (956) ts_spi: Initializing SPI subsystem +I (961) ts_uart: Initializing UART subsystem +I (966) ts_adc: Initializing ADC subsystem +I (971) ts_hal: HAL initialization complete, platform: ESP32S3 +I (2024) ts_service: Service 'hal' started in 89 ms +I (2029) ts_service: === Phase 3: DRIVER === +I (2033) ts_service: Starting 4 services in phase DRIVER +I (2038) ts_service: Starting service: power +I (2042) ts_services: Initializing power service... +I (999) ts_power_policy: Initializing power policy v1.0.0 +I (1006) ts_power_policy: NVS: enabled_on_boot = true +I (1011) ts_power_policy: Registered SD card mount event handler +I (1018) ts_power_policy: Power policy initialized (Low: 12.6V, Recovery: 18.0V, Delay: 60s) [source: defaults] +I (2076) ts_power_monitor: Initializing power monitor v1.0.0 +I (2081) ts_power_monitor: Initializing voltage monitor on GPIO 18 (ADC2_CH7) +I (2088) ts_power_monitor: ADC calibration initialized +I (2093) ts_power_monitor: Voltage monitor initialized (divider ratio: 11.4:1) +I (2100) ts_power_monitor: Initializing power chip communication on GPIO 47 (UART1) +I (2107) uart: queue free spaces: 10 +I (2110) ts_power_monitor: Power chip communication initialized (baud: 9600) +I (2117) ts_power_monitor: Power monitor initialized successfully +I (2123) ts_services: Starting power service... +I (2127) ts_power_monitor: Starting power monitor +I (2131) ts_power_monitor: Power monitor task started +I (2136) ts_power_monitor: Power monitor started +I (1094) ts_power_policy: Starting power policy monitoring +I (1100) ts_power_policy: Power policy task started +I (1106) ts_power_policy: Power policy monitoring started +I (2158) ts_services: Power protection started (auto-start enabled) +I (2164) ts_service: Service 'power' started in 123 ms +I (2169) ts_service: Starting service: drivers +I (2173) ts_services: Initializing drivers service... +I (1131) ts_drivers: Initializing device drivers +I (1137) ts_temp_source: Loaded preferred source from NVS: variable +I (1145) ts_temp_source: Loaded 1 weighted bound vars from NVS +I (1150) ts_temp_source: Temperature source manager initialized (v1.0.0), preferred: variable +I (1159) ts_drivers: Temperature source manager initialized +I (1166) ts_fan: Subscribed to temperature events +I (1171) ts_fan: Fan driver initialized +I (1176) ts_fan: Fan 0 configured: PWM=GPIO41, TACH=-1, curve=0 points +I (1183) ts_drivers: Fan 0 configured on GPIO 41 +I (1188) ts_power: Power monitor initialized +I (1193) ts_device: Device control initialized +I (1198) ts_device: AGX configured: FORCE_SHUTDOWN=GPIO3(LOW=run), RESET=GPIO1(LOW=normal) +I (1207) ts_drivers: AGX configured (pwr=3, rst=1, rcv=40) +I (1213) ts_device: LPMU configured (power=46[pulse HIGH], reset=2[pulse HIGH]) +I (1221) ts_drivers: LPMU configured (pwr=46, rst=2) +I (1227) ts_usb_mux: USB MUX driver initialized +I (1232) ts_usb_mux: Loaded USB MUX target from NVS: 0 +I (1238) ts_usb_mux: USB MUX -> ESP32 (sel0=0, sel1=0) +I (1244) ts_usb_mux: USB MUX configured (sel0=8, sel1=48), restored target: 0 +I (1251) ts_drivers: USB MUX configured (sel0=8, sel1=48) +I (2304) ts_compute_monitor: Initializing compute monitor v1.0.0 +I (1263) ts_temp_source: Provider registered: agx_cpu (agx) +I (2316) ts_compute_monitor: Initialized, server: 10.10.99.98:58090 +I (1276) ts_drivers: Compute monitor initialized (use 'compute --start' to connect) +I (1284) ts_drivers: Device drivers initialized +I (1290) ts_fan: Restored fan 0: mode=2, duty=25%, curve=9 pts +I (2342) ts_service: Service 'drivers' started in 169 ms +I (2347) ts_service: Starting service: led +I (2351) ts_services: Initializing LED service... +I (1309) led_cc: Loaded config from NVS +I (1314) led_cc: Color correction initialized (enabled=true) +I (1320) ts_led: LED subsystem initialized +I (2371) ts_services: Starting LED service... +I (1329) led_preset: Touch LED: using hardcoded GPIO 45 +I (1334) led_driver: Using RMT backend for 1 LEDs on GPIO 45 +I (1342) led_driver: LED driver initialized: 'led_touch' - GPIO 45, 1 LEDs +I (1348) ts_led: Created LED device 'led_touch' with 1 LEDs +I (1355) led_preset: Touch LED initialized: 1 LEDs on GPIO 45 +I (1361) led_preset: Board LED: using hardcoded GPIO 42 +I (1367) led_driver: Using RMT backend for 28 LEDs on GPIO 42 +I (1375) led_driver: LED driver initialized: 'led_board' - GPIO 42, 28 LEDs +I (1381) ts_led: Created LED device 'led_board' with 28 LEDs +I (1387) led_preset: Board LED initialized: 28 LEDs on GPIO 42 +I (1394) led_preset: Matrix LED: pin_manager returned GPIO 9 +I (1400) led_driver: Using SPI backend for 1024 LEDs on GPIO 9 +I (1438) led_driver: LED driver initialized: 'led_matrix' - GPIO 9, 1024 LEDs +I (1439) ts_led: Created LED device 'led_matrix' with 1024 LEDs +I (1442) led_preset: Matrix LED initialized: 32x32 on GPIO 9 +I (1448) led_preset: Loading LED boot configurations... +I (1461) led_preset: Restored touch: animation=solid, speed=50, brightness=80, color=#FFCCCC +I (1465) led_preset: Restored board: animation=solid, speed=50, brightness=60, color=#FFFFFF +I (1474) led_preset: Restored matrix: animation=solid, speed=50, brightness=52, color=#FFFFFF +I (2529) ts_service: Service 'led' started in 178 ms +I (2533) ts_service: Starting service: storage +I (2537) ts_services: Initializing storage service... +I (1499) ts_storage: Storage subsystem initialized +I (2547) ts_services: Starting storage service... +I (1505) storage_spiffs: Mounting SPIFFS at /spiffs (partition: storage) +I (1549) storage_spiffs: SPIFFS mounted: 474641 total, 0 used, 474641 free +I (2597) ts_services: SPIFFS mounted at /spiffs +I (1551) storage_sd: Good: /sdcard not in FATFS s_fat_ctxs[] (info returned ESP_ERR_INVALID_STATE) +I (1560) storage_sd: Mounting SD card at /sdcard (mode: 2, freq: 20000 kHz) +I (1568) storage_sd: SD GPIO: CMD=15, CLK=16, D0=4, D1=5, D2=6, D3=7 +I (1634) storage_sd: SD card mounted: +I (1635) storage_sd: Name: MSSD0 +I (1635) storage_sd: Type: SDHC/SDXC +I (2682) ts_config: Saving configuration... +I (1636) storage_sd: Speed: default +I (1645) storage_sd: Size: 29850MB +I (2693) ts_config: Saved configuration to backend 1 +I (1656) ts_power_policy: SD card mounted, syncing power policy config... +I (2703) ts_config: Configuration saved +I (2712) ts_config_pack: Loaded plain config: /sdcard/config/power_policy.json (180 bytes) +I (1673) ts_power_policy: SD: low_voltage_threshold = 12.60V +I (1679) ts_power_policy: SD: recovery_voltage_threshold = 18.00V +I (1686) ts_power_policy: SD: shutdown_delay_sec = 60 +I (1692) ts_power_policy: SD: recovery_hold_sec = 5 +I (1697) ts_power_policy: SD: fan_stop_delay_sec = 60 +I (2708) ts_services: SD card mounted at /sdcard +I (1703) ts_power_policy: SD: enabled_on_boot = true +I (1713) ts_power_policy: Loaded power policy config from SD card +I (1720) ts_power_policy: Config loaded from SD card, syncing to NVS +I (2774) ts_config: Saving configuration... +I (2784) ts_config: Saved configuration to backend 1 +I (2784) ts_config: Configuration saved +I (2785) ts_config_file: SD card mounted, loading configuration files... +I (2778) ts_recovery: Checking for SD card recovery... +I (2793) ts_config_file: Loading configuration files from: /sdcard/config +I (2806) ts_recovery: No recovery directory found +I (2807) ts_config_file: Loading: power_policy.json +I (2812) ts_config_json: Loading JSON config: /sdcard/config/power_policy.json +I (2820) ts_service: Service 'storage' started in 282 ms +I (2822) ts_config_json: JSON config loaded successfully +I (2830) ts_config_file: Loading: led_color_correction.json +I (2835) ts_config_json: Loading JSON config: /sdcard/config/led_color_correction.json +I (2836) ts_service: === Phase 4: NETWORK === +I (2846) ts_config_json: JSON config loaded successfully +I (2852) ts_config_file: Loading: fan_curve_config_0.json +I (2856) ts_config_json: Loading JSON config: /sdcard/config/fan_curve_config_0.json +I (2865) ts_service: Starting 1 services in phase NETWORK +I (2869) ts_config_json: JSON config loaded successfully +I (2875) ts_config_file: Loading: fan.json +I (2878) ts_config_json: Loading JSON config: /sdcard/config/fan.json +I (2878) ts_service: Starting service: network +I (2887) ts_config_json: JSON config loaded successfully +I (2894) ts_config_file: Loading: ui_widgets.json +I (2898) ts_config_json: Loading JSON config: /sdcard/config/ui_widgets.json +I (2905) ts_services: Initializing network service... +I (2908) ts_config_json: JSON config loaded successfully +I (2915) ts_config_file: Loaded 5 JSON configs, skipped 1 +I (2919) ts_config_file: Configuration files loaded successfully +I (1874) ts_net_mgr: Initializing network manager... +I (1884) ts_net_mgr: No saved config in NVS, using defaults +I (1891) ts_net_mgr: Ethernet pins: MOSI=11 MISO=13 SCLK=12 CS=10 INT=38 RST=39 +I (1898) ts_eth: Initializing Ethernet (W5500) +I (1904) ts_eth: Created Ethernet netif with DHCP server mode +I (1914) ts_eth: Device IP: 10.10.99.97 +I (1914) ts_eth: Gateway: 10.10.99.100 +I (1919) ts_eth: Netmask: 255.255.255.0 +I (1953) ts_eth: Ethernet MAC: 20:6e:f1:a1:d5:8f +I (3000) esp_eth.netif.netif_glue: 20:6e:f1:a1:d5:8f +I (3001) esp_eth.netif.netif_glue: ethernet attached to netif +I (1958) ts_eth: DHCP lease range configured: 10.10.99.100 - 10.10.99.103 +I (1965) ts_eth: DHCP DNS server configured: 8.8.8.8 +I (1971) ts_eth: Ethernet initialized +I (1975) ts_net_mgr: Ethernet initialized, MAC: 20:6e:f1:a1:d5:8f +I (1982) ts_net_mgr: Network manager initialized +I (1992) ts_dhcps: Initializing DHCP server... +I (1992) ts_dhcps: DHCP event task started +I (1997) ts_dhcps: No saved config, using defaults +I (2003) ts_dhcps: DHCP server initialized (event queue enabled) +I (3056) ts_services: Starting network service... +I (2014) ts_net_mgr: Starting Ethernet... +I (2019) ts_net_mgr: Using static IP: 10.10.99.97 +I (2040) ts_net_mgr: Ethernet started +I (2040) ts_eth: Ethernet started +I (2041) ts_net_mgr: Ethernet started, waiting for link... +I (3091) ts_time_sync: Timezone set to: CST-8 +I (3095) ts_time_sync: Time sync module initialized +I (3099) ts_time_sync: NTP server 1: 10.10.99.99 +I (3104) ts_time_sync: NTP server 2: 10.10.99.98 +I (3108) ts_time_sync: NTP server 3: 10.10.99.100 +I (3116) ts_time_sync: Starting NTP sync with primary: 10.10.99.99, secondary: 10.10.99.98 +I (3121) ts_time_sync: NTP synchronization started (retry enabled for unreliable servers) +I (2082) ts_device: LPMU startup detection: waiting for network... +I (2089) ts_device: LPMU startup detection task started +I (3141) ts_service: Service 'network' started in 237 ms +I (3147) ts_service: === Phase 5: SECURITY === +I (3156) ts_service: Starting 1 services in phase SECURITY +I (3156) ts_service: Starting service: security +I (3160) ts_services: Initializing security service... +I (3167) ts_ssh_hosts_cfg: NVS has 0 hosts, will load from SD card in background +I (3172) ts_ssh_hosts_cfg: SSH hosts config initialized (SD card loading deferred) +I (3215) ts_ssh_cmd_cfg: NVS has 6 commands, will load from SD card in background +I (3216) ts_ssh_cmd_cfg: SSH commands config initialized (SD card loading deferred) +I (2173) ts_security: Security subsystem initialized +I (3225) ts_keystore: Initializing secure keystore... +I (3234) ts_keystore: Keystore initialized +I (3234) ts_known_hosts: Known hosts module initialized +I (3397) ts_cert: Initialized, status: activated, has_key=1, has_cert=1 +I (3398) pki_client: PKI client initialized, server=10.10.99.100:57443, device_id=TIANSHAN-DEVICE-001 +I (3402) ts_services: Certificate status: activated, time validity: valid +I (3409) ts_config_pack: Config pack system initialized, device fingerprint: 50c2e523d3483956... +I (3417) ts_config_file: Loading encrypted configuration files from: /sdcard/config +I (3432) ts_service: Service 'security' started in 272 ms +I (3432) ts_service: === Phase 6: SERVICE === +I (3434) ts_service: Starting 3 services in phase SERVICE +I (3439) ts_service: Starting service: automation +I (3443) ts_services: Initializing automation service... +I (3448) ts_automation: Initializing automation engine v1.0.0 +I (3459) ts_source_mgr: Initializing source manager (max 16) +I (3468) ts_source_mgr: Source manager initialized (loading deferred) +I (3469) ts_rule_engine: Initializing rule engine (max 32 rules) +I (3471) ts_rule_engine: Rule engine initialized (loading deferred) +I (3477) ts_action_mgr: Initializing action manager +I (3483) ts_action_mgr: Action executor task started (DRAM stack) +I (3487) ts_action_mgr: Action manager initialized (loading deferred) +I (3493) ts_automation: Loading config from: /sdcard/config/automation.json +I (3509) ts_ssh_cmd_cfg: Pre-creating variables for all SSH commands +I (2500) ts_power_policy: Registered 8 automation variables for power policy +I (3547) ts_automation: Automation engine initialized +I (3548) ts_services: Starting automation service... +I (3553) ts_source_mgr: Starting all data sources +I (3908) ts_config: Saving configuration... +I (3919) ts_config: Saved configuration to backend 1 +I (3919) ts_config: Configuration saved +I (4041) ts_net_mgr: Ethernet link up +I (4042) ts_net_mgr: Ethernet IP (static/DHCPS): 10.10.99.97 +I (4042) ts_net: mDNS disabled by config +I (4046) ts_eth: Ethernet link up +I (4050) ts_eth: Ethernet MAC: 20:6e:f1:a1:d5:8f +I (5171) ts_source_mgr: Network ready, starting external sources +I (5171) ts_automation: Automation task started +I (5171) ts_services: Automation engine running: 0 sources, 0 rules, 36 variables +I (5177) ts_service: Service 'automation' started in 1734 ms +I (5190) ts_service: Starting service: https +I (5191) ts_https: HTTPS server deinitialized +I (5191) ts_https: HTTPS server initialized (port=443, mTLS=required) +I (4149) ts_dhcps: Starting DHCP server on ethernet... +I (5197) ts_https_api: Registering permission test endpoints... +I (4156) ts_dhcps: Ethernet IP preserved: 10.10.99.97 +I (5208) ts_https: Registered endpoint: GET / (min_role=anonymous) +I (4168) ts_dhcps: I (5220) ts_https: Registered endpoint: GET /api/auth/whoami (min_role=viewer) +I (5230) ts_https: Registered endpoint: GET /api/test/viewer (min_role=viewer) +I (5236) ts_https: Registered endpoint: GET /api/test/operator (min_role=operator) +Applied config for ethernet: +I (5246) ts_https: Registered endpoint: GET /api/test/admin (min_role=admin) +I (4199) ts_dhcps: Gateway: 10.10.99.100 +I (5253) ts_https: Registered endpoint: POST /api/test/admin-action (min_role=admin) +I (4211) ts_dhcps: Pool: 10.10.99.100 - 10.10.99.103 +I (5265) ts_https: mTLS enabled: client certificates required +I (5277) esp_https_server: Starting server +I (4225) ts_dhcps: Lease: 1440 min +I (5284) esp_https_server: Server listening on port 443 +I (4238) ts_dhcps: DHCP server started on ethernet +I (5291) ts_https: HTTPS server started on port 443 with 6 endpoints +I (4249) ts_eth: DHCP server started via ts_dhcp_server +I (5253) ts_ssh_cmd_cfg: Deferred: checking SD card for config (NVS has 6 commands)... +I (5317) ts_ssh_cmd_cfg: SD card has config, clearing NVS and importing... +I (5197) ts_service: Service 'https' started in 6 ms +I (5327) ts_service: Starting service: api +I (5330) ts_services: Initializing API service... +I (4288) ts_api: API endpoints allocated in PSRAM (25344 bytes) +I (5336) ts_ssh_cmd_cfg: Cleared all SSH commands +I (4294) ts_api: API layer initialized (max 288 endpoints) +I (5350) ts_ssh_cmd_cfg: Cleared all SSH commands +I (5352) ts_services: Starting API service... +I (5365) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3_6-35B-A3B.json (1095 bytes) +I (5397) ts_ssh_cmd_cfg: Added SSH command: Qwen3.6-35B-A3B (Qwen3_6-35B-A3B) +I (5407) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3-Embedding-0_6B.json (885 bytes) +I (4361) ts_api: Registering all API modules... +I (4366) api_config: Config API registered (11 endpoints) +I (4370) api_device: Registering device APIs +I (4377) api_led: Registering LED APIs +I (4381) api_network: Registering network APIs +I (4388) api_fan: Registering fan APIs +I (4390) api_power: Registering power APIs +I (5466) ts_ssh_cmd_cfg: Added SSH command: Qwen3-Embedding-0.6B (Qwen3-Embedding-0_6B) +I (4422) api_temp: Registering temperature APIs +I (4427) api_service: Registering service APIs... +I (5477) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3-Reranker-0_6B.json (1064 bytes) +I (4431) api_service: Service APIs registered (5 endpoints) +I (4448) api_storage: Registering storage APIs... +I (4468) api_storage: Storage APIs registered (9 endpoints) +I (4468) api_gpio: Registering GPIO APIs... +I (4469) api_gpio: GPIO APIs registered (4 endpoints) +I (4475) api_monitor: Registering monitor APIs... +I (4480) api_monitor: Monitor APIs registered: 6 endpoints +I (4491) api_ssh: Registering SSH APIs... +I (5557) ts_ssh_cmd_cfg: Added SSH command: Qwen3-Reranker-0.6B (Qwen3-Reranker-0_6B) +I (5565) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/drop.json (395 bytes) +I (4548) api_sftp: Registering SFTP APIs... +I (5597) ts_api_ota: Registering OTA APIs +I (5615) ts_ota: Running from partition: ota_0 (addr=0x20000, size=3072 KB) +I (5616) ts_ota: OTA subsystem initialized +I (5626) ts_ssh_cmd_cfg: Added SSH command: drop (drop) +I (5627) ts_api_ota: Loaded OTA server URL: (not set) +I (5634) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3_8_27B_Quark_INT4_MTP3.json (672 bytes) +I (5664) ts_api_ota: Registered 21 OTA API endpoints +I (4621) api_log: Log API endpoints registered +I (4623) api_automation: Registering automation APIs +I (5679) ts_ssh_hosts_cfg: Deferred: checking SD card for config (NVS has 0 hosts)... +I (5682) ts_ssh_hosts_cfg: SD card has config, clearing NVS and importing... +I (4639) api_automation: Automation APIs registered +I (4664) api_cert: Certificate APIs registered +I (5741) ts_ssh_cmd_cfg: Added SSH command: Qwen3.8-27B-Quark-INT4-MTP3 (Qwen3_8_27B_Quark_INT4_MTP3) +I (5752) ts_ssh_hosts_cfg: Cleared all SSH host configs +I (5763) ts_ssh_hosts_cfg: Cleared all SSH host configs +I (5768) ts_config_pack: Loading encrypted config: /sdcard/config/ssh_hosts/rm01@10.10.99.98.tscfg +I (4722) ts_auth: Auth module initialized (version 3) +I (5774) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/quark_stop_repair.json (472 bytes) +I (5851) ts_ssh_cmd_cfg: Async sync to SD card... +I (5861) ts_ssh_cmd_cfg: Async sync to SD card... +I (5882) ts_ssh_cmd_cfg: Added SSH command: Quark进程与内存检查 (quark_stop_repair) +I (5888) ts_ssh_cmd_cfg: Loaded 6 SSH commands from directory: /sdcard/config/ssh_commands (skipped 0) +I (4860) api_auth: Auth APIs registered +I (4867) api_ui: Registering UI APIs +I (4884) api_config_pack: Config Pack API registered (8 endpoints) +I (4901) ts_api: All API modules registered (263 endpoints) +I (5956) ts_service: Service 'api' started in 625 ms +I (5961) ts_service: === Phase 7: UI === +I (5965) ts_service: Starting 2 services in phase UI +I (5973) ts_source_mgr: Deferred source loading started +I (5973) ts_service: Starting service: console +I (5998) ts_services: Initializing console service... +I (4955) ts_i18n: I18n initialized, language: English +I (6021) ts_ssh_cmd_cfg: Exported 6 SSH commands to /sdcard/config/ssh_commands/ +I (4986) ts_console: Console initialized +I (5004) cmd_register: Registering all console commands... +I (5029) cmd_system: System commands registered +I (5045) cmd_service: Service commands registered +I (5054) cmd_config: Config commands registered (with pack support) +I (5080) cmd_fan: Fan commands registered (API mode) +I (5093) cmd_storage: Storage commands registered +I (6161) ts_ssh_cmd_cfg: Exported 6 SSH commands to /sdcard/config/ssh_commands/ +I (6193) ts_ssh_cmd_cfg: Loaded 6 commands from SD card (.tscfg > .json) +I (5154) cmd_net: Network commands registered +I (5156) cmd_device: Device commands registered +I (5160) cmd_led: LED commands registered +I (5162) cmd_wifi: WiFi commands registered +I (5173) ts_nat: Initializing NAT module +I (5174) ts_nat: No saved NAT config, using defaults +I (5176) ts_nat: NAT module initialized (auto_start=yes) +I (5195) cmd_key: Registered command: key +I (5197) cmd_ssh: Registered command: ssh +I (6216) ts_config_pack: Loaded plain config: /sdcard/config/sources/agx-info.json (192 bytes) +I (6253) ts_ssh_hosts_cfg: Async sync to SD card... +I (5199) cmd_sftp: Registered command: sftp +I (6262) ts_ssh_hosts_cfg: Exported 0 SSH hosts to /sdcard/config/ssh_hosts/ +I (6264) ts_ssh_hosts_cfg: Async sync to SD card... +I (5217) cmd_hosts: Registered command: hosts +I (6285) ts_ssh_hosts_cfg: Exported 0 SSH hosts to /sdcard/config/ssh_hosts/ +I (6265) ts_source_mgr: Loaded 1 sources from directory: /sdcard/config/sources +I (6298) ts_source_mgr: Loaded 1 sources from SD card directory +I (5242) cmd_fs: File system commands registered: 9 succeeded, 0 failed +I (6325) cmd_gpio: GPIO command registered (high priority) +I (6328) cmd_ota: OTA command registered +I (5283) cmd_pki: Registered 'pki' command +I (6332) cmd_auto: Command 'auto' registered +I (5287) cmd_register: Command registration complete: 24 succeeded, 0 failed +I (6346) ts_services: Starting console service... +I (5301) ts_console: Console task started +TianShanOS> I (6350) ts_source_mgr: Exported 1 sources to directory: /sdcard/config/sources +I (6365) ts_source_mgr: Saved 1 sources to NVS and SD card +I (6366) ts_source_mgr: Deferred source loading complete: 1 sources +I (6372) ts_config_pack: Successfully loaded encrypted config: /sdcard/config/ssh_hosts/rm01@10.10.99.98.tscfg +I (5302) ts_console: Console started +I (6378) ts_source_mgr: Starting loaded data sources... +W (6399) ts_ssh_hosts_cfg: SD card import failed: ESP_ERR_NOT_FOUND +I (6400) ts_source_mgr: Starting all data sources +I (6411) ts_source_mgr: Network ready, starting external sources +I (6412) ts_source_mgr: Starting Socket.IO source: agx-info +I (6424) ts_source_mgr: SIO [agx-info] connection started +I (6405) ts_service: Service 'console' started in 407 ms +I (6427) ts_service: Starting service: webui +I (6447) websocket_client: Started +I (6450) ts_services: Initializing WebUI service... +I (6471) ts_rule_engine: Deferred rule loading started +I (6485) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3.6-35B-A3B.json (281 bytes) +I (6508) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3-Embedding-0.6B.json (301 bytes) +I (6529) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3-Reranker-0.6B.json (297 bytes) +I (6555) ts_config_pack: Loaded plain config: /sdcard/config/rules/drop.json (245 bytes) +I (6575) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3_8_27B_Quark_INT4_MTP3.json (324 bytes) +I (6579) ts_rule_engine: Deferred rule loading complete: 5 rules +I (6814) ts_services: Mounted www partition at /www (2541877/2884241 bytes) +I (5768) ts_webui: Initializing WebUI +I (5769) ts_http: HTTP server initialized +I (5780) ts_webui: WebUI initialized +I (6827) ts_services: Starting WebUI service... +I (5783) ts_http: HTTP server started on port 80 +I (5794) webui_api: Initializing API routes +I (5797) webui_api: API routes registered +I (5798) webui_ws: Initializing WebSocket with Terminal support +I (5809) webui_ws: Terminal buffer allocated in PSRAM (32768 bytes) +I (5811) webui_ws: Power policy event handler registered +I (5822) webui_ws: WebSocket handler registered at /ws +I (5823) ts_webui: WebUI started +I (6881) ts_services: WebUI server started on port 80 +I (6882) ts_service: Service 'webui' started in 432 ms +I (6882) ts_service: All services started in 4969 ms +I (6894) ts_core: TianShanOS started +I (6894) main: TianShanOS started successfully! +I (6895) main: Build: Sep 28 2026 18:02:01 +I (6906) ts_service: === Service Status === +I (6907) ts_service: Total: 12, Running: 12, Stopped: 0, Error: 0 +I (6918) ts_service: Startup time: 4969 ms +I (6918) ts_service: [SERVICE] automation - RUNNING (1734 ms) +I (6919) ts_service: [UI] console - RUNNING (407 ms) +I (6934) ts_service: [UI] webui - RUNNING (432 ms) +I (6935) ts_service: [SERVICE] https - RUNNING (6 ms) +I (6936) ts_service: [SERVICE] api - RUNNING (625 ms) +I (6947) ts_service: [SECURITY] security - RUNNING (272 ms) +I (6948) ts_service: [NETWORK] network - RUNNING (237 ms) +I (6959) ts_service: [DRIVER] power - RUNNING (123 ms) +I (6960) ts_service: [DRIVER] drivers - RUNNING (169 ms) +I (6973) ts_service: [DRIVER] led - RUNNING (178 ms) +I (6974) ts_service: [DRIVER] storage - RUNNING (282 ms) +I (6975) ts_service: [HAL] hal - RUNNING (89 ms) +I (6986) ts_service: ====================== +I (6986) main: Entering main loop... +I (6988) ts_action_mgr: Deferred action template loading started +I (7008) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3.6-35B-A3B.json (190 bytes) +I (7016) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3-Embedding-0.6B.json (205 bytes) +I (7024) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3-Reranker-0.6B.json (202 bytes) +I (7032) ts_config_pack: Loaded plain config: /sdcard/config/actions/drop.json (157 bytes) +I (7041) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3_8_27B_Quark_INT4_MTP3.json (272 bytes) +I (7054) ts_action_mgr: Loaded 5 templates from directory: /sdcard/config/actions +I (7055) ts_action_mgr: Loaded 5 action templates from SD card directory +I (7184) ts_action_mgr: Exported 5 templates to directory: /sdcard/config/actions +I (7186) ts_action_mgr: Saved 5 action templates to NVS and SD card +I (7197) ts_action_mgr: Deferred action template loading complete: 5 templates +I (7088) ts_device: LPMU startup detection: checking if LPMU is online... +I (7093) ts_device: LPMU detected online at 10.10.99.99, setting state to ON +I (94537) ts_config_pack: Loaded plain config: /sdcard/config/ui_widgets.json (480 bytes) +I (93493) api_ui: Loaded widgets from SD card +I (93494) api_ui: Loaded UI widgets config (source: sdcard) +I (96487) ts_security: Session created: 386af091 +I (96488) ts_auth: User root logged in (level 4, session 386af091) +I (97706) ts_config_pack: Loaded plain config: /sdcard/config/ui_widgets.json (480 bytes) +I (96661) api_ui: Loaded widgets from SD card +I (96663) api_ui: Loaded UI widgets config (source: sdcard) +I (99383) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (112607) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (113659) ts_ssh: SSH client initialized (libssh2 version: 1.10.1_DEV) +I (114229) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (114454) ts_shell: Interactive shell opened + +TianShanOS Console Commands +============================ + +[System] + hexdump + mv + cp + rm + mkdir + pwd + cd + cat + ls + dhcp + storage + service + system + lang + echo + clear + reboot + sysinfo + version + help + +[Configuration] + config + +[LED] + led + +[Fan] + fan + +[Network] + wifi + net + +[Device] + device + +[Debug] + log + free + tasks + +Use ' --help' for command details + +I (334884) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (336502) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (336710) ts_shell: Interactive shell opened +I (377695) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (379307) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (379712) ts_shell: Interactive shell opened +I (434939) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (436558) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (436971) ts_shell: Interactive shell opened +I (505756) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (507371) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (507731) ts_shell: Interactive shell opened +I (544589) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (546199) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (546489) ts_shell: Interactive shell opened +I (598411) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (600027) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (600239) ts_shell: Interactive shell opened +I (650760) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (652371) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (652745) ts_shell: Interactive shell opened +I (711464) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (713083) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (713493) ts_shell: Interactive shell opened +I (760262) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (761875) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (762246) ts_shell: Interactive shell opened +I (788583) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (789816) ts_config_pack: Loaded plain config: /sdcard/config/ui_widgets.json (480 bytes) +I (788772) api_ui: Loaded widgets from SD card +I (788773) api_ui: Loaded UI widgets config (source: sdcard) diff --git a/docs/repair/ssh-poll-stack/device-candidate/summary.json b/docs/repair/ssh-poll-stack/device-candidate/summary.json new file mode 100644 index 0000000..2b42030 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/summary.json @@ -0,0 +1,82 @@ +[ + { + "round": 1, + "minimum_hwm_bytes": 4096, + "closed_ssh_poll_count": 0, + "free_heap": 7672364, + "psram_free": 7614416, + "uptime_ms": 319336 + }, + { + "round": 2, + "minimum_hwm_bytes": 4108, + "closed_ssh_poll_count": 0, + "free_heap": 7672156, + "psram_free": 7614208, + "uptime_ms": 368074 + }, + { + "round": 3, + "minimum_hwm_bytes": 4096, + "closed_ssh_poll_count": 0, + "free_heap": 7671944, + "psram_free": 7613996, + "uptime_ms": 408198 + }, + { + "round": 4, + "minimum_hwm_bytes": 4096, + "closed_ssh_poll_count": 0, + "free_heap": 7671944, + "psram_free": 7613996, + "uptime_ms": 468330 + }, + { + "round": 5, + "minimum_hwm_bytes": 4096, + "closed_ssh_poll_count": 0, + "free_heap": 7671940, + "psram_free": 7613996, + "uptime_ms": 536996 + }, + { + "round": 6, + "minimum_hwm_bytes": 4108, + "closed_ssh_poll_count": 0, + "free_heap": 7671940, + "psram_free": 7613996, + "uptime_ms": 574826 + }, + { + "round": 7, + "minimum_hwm_bytes": 4096, + "closed_ssh_poll_count": 0, + "free_heap": 7671720, + "psram_free": 7613768, + "uptime_ms": 629959 + }, + { + "round": 8, + "minimum_hwm_bytes": 4096, + "closed_ssh_poll_count": 0, + "free_heap": 7670896, + "psram_free": 7613204, + "uptime_ms": 684751 + }, + { + "round": 9, + "minimum_hwm_bytes": 3952, + "closed_ssh_poll_count": 0, + "free_heap": 7671940, + "psram_free": 7613996, + "uptime_ms": 749250 + }, + { + "round": 10, + "minimum_hwm_bytes": 3876, + "closed_ssh_poll_count": 0, + "free_heap": 7671576, + "psram_free": 7613736, + "uptime_ms": 795443 + } +] \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-candidate/welcome.json b/docs/repair/ssh-poll-stack/device-candidate/welcome.json new file mode 100644 index 0000000..e4941db --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-candidate/welcome.json @@ -0,0 +1,229 @@ +{ + "stage": "welcome_and_echo", + "time": "2026-09-28T18:12:24.041494", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1108, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 688, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1596, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 908, + "core": 0, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1336, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 392, + "core": 0, + "state": "blocked" + }, + { + "name": "ssh_poll", + "priority": 5, + "stack_hwm": 4096, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15124, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 496, + "core": 1, + "state": "suspended" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2680, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2160, + "core": 1, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + } + ], + "count": 25 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7601348, + "min_free_heap": 7550256, + "internal": { + "total": 308035, + "free": 72459, + "allocated": 235576, + "largest_block": 31744 + }, + "psram": { + "total": 8370236, + "free": 7544404, + "allocated": 825832, + "largest_block": 7471104 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 147627 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/automatic-rounds-verified.log b/docs/repair/ssh-poll-stack/device-diagnostic/automatic-rounds-verified.log new file mode 100644 index 0000000..a12ddbf --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/automatic-rounds-verified.log @@ -0,0 +1,10 @@ +{"round":2,"minimumObservedHwm":3984,"free_heap":7617308,"psram_free":7595964,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":3,"minimumObservedHwm":3996,"free_heap":7616864,"psram_free":7595524,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":4,"minimumObservedHwm":3984,"free_heap":7616384,"psram_free":7595044,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":5,"minimumObservedHwm":3984,"free_heap":7614940,"psram_free":7593732,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":6,"minimumObservedHwm":3644,"free_heap":7612656,"psram_free":7587612,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":7,"minimumObservedHwm":3984,"free_heap":7615172,"psram_free":7593832,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":8,"minimumObservedHwm":3984,"free_heap":7615952,"psram_free":7594616,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":9,"minimumObservedHwm":3996,"free_heap":7615960,"psram_free":7594620,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +{"round":10,"minimumObservedHwm":3984,"free_heap":7616184,"psram_free":7594840,"statuses":["connecting","connected","disconnecting","closed"],"echoVerified":true,"pollerGone":true} +NINE_AUTOMATIC_ROUNDS_COMPLETE diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/automatic-rounds.log b/docs/repair/ssh-poll-stack/device-diagnostic/automatic-rounds.log new file mode 100644 index 0000000..03a961a --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/automatic-rounds.log @@ -0,0 +1,9 @@ +file:///private/tmp/tianshan-ssh-stack-diagnostic/rounds.mjs:14 + async function wait(fn,ms=15000){const end=Date.now()+ms;while(!fn()){if(err)throw err;if(Date.now()>end)throw Error('Stage timed out; no command retry');await sleep(50);}} + ^ + +Error: Stage timed out; no command retry + at wait (file:///private/tmp/tianshan-ssh-stack-diagnostic/rounds.mjs:14:113) + at async file:///private/tmp/tianshan-ssh-stack-diagnostic/rounds.mjs:23:3 + +Node.js v24.10.0 diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/automatic-samples.jsonl b/docs/repair/ssh-poll-stack/device-diagnostic/automatic-samples.jsonl new file mode 100644 index 0000000..bda28db --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/automatic-samples.jsonl @@ -0,0 +1,38 @@ +{"time":"2026-09-28T10:28:52.179Z","stage":"round2_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7618492,"min_free_heap":7469732,"internal":{"total":269215,"free":25539,"allocated":243676,"largest_block":8692},"psram":{"total":8359952,"free":7596964,"allocated":762988,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":265787}}} +{"time":"2026-09-28T10:28:55.399Z","stage":"round2_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3996,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7546448,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359536,"free":7526212,"allocated":833324,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":268969}}} +{"time":"2026-09-28T10:29:49.289Z","stage":"round2_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7617320,"min_free_heap":7469732,"internal":{"total":269199,"free":25407,"allocated":243792,"largest_block":8692},"psram":{"total":8359840,"free":7595932,"allocated":763908,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":322934}}} +{"time":"2026-09-28T10:29:52.435Z","stage":"round2_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7545964,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359504,"free":7525724,"allocated":833780,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":326001}}} +{"time":"2026-09-28T10:29:52.599Z","stage":"round2_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7545176,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359488,"free":7524936,"allocated":834552,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":326267}}} +{"time":"2026-09-28T10:29:52.868Z","stage":"round2_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7617308,"min_free_heap":7469732,"internal":{"total":269183,"free":25359,"allocated":243824,"largest_block":8692},"psram":{"total":8359856,"free":7595964,"allocated":763892,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":326522}}} +{"time":"2026-09-28T10:29:53.578Z","stage":"round3_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7617588,"min_free_heap":7469732,"internal":{"total":269215,"free":25539,"allocated":243676,"largest_block":8692},"psram":{"total":8359888,"free":7596068,"allocated":763820,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":327129}}} +{"time":"2026-09-28T10:29:56.646Z","stage":"round3_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3996,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7545536,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359472,"free":7525296,"allocated":834176,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":330234}}} +{"time":"2026-09-28T10:29:56.837Z","stage":"round3_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ssh_poll","priority":5,"stack_hwm":3996,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544844,"min_free_heap":7469732,"internal":{"total":268975,"free":24123,"allocated":244852,"largest_block":8692},"psram":{"total":8359392,"free":7524736,"allocated":834656,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":330527}}} +{"time":"2026-09-28T10:29:57.177Z","stage":"round3_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616864,"min_free_heap":7469732,"internal":{"total":269183,"free":25359,"allocated":243824,"largest_block":8692},"psram":{"total":8359824,"free":7595524,"allocated":764300,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":330859}}} +{"time":"2026-09-28T10:29:57.910Z","stage":"round4_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7617136,"min_free_heap":7469732,"internal":{"total":269215,"free":25539,"allocated":243676,"largest_block":8692},"psram":{"total":8359856,"free":7595616,"allocated":764240,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":331475}}} +{"time":"2026-09-28T10:30:00.916Z","stage":"round4_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7545072,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359440,"free":7524820,"allocated":834620,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":334498}}} +{"time":"2026-09-28T10:30:01.103Z","stage":"round4_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7545072,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359440,"free":7524820,"allocated":834620,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":334786}}} +{"time":"2026-09-28T10:30:01.426Z","stage":"round4_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616384,"min_free_heap":7469732,"internal":{"total":269183,"free":25359,"allocated":243824,"largest_block":8692},"psram":{"total":8359792,"free":7595044,"allocated":764748,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":335098}}} +{"time":"2026-09-28T10:30:02.146Z","stage":"round5_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616684,"min_free_heap":7469732,"internal":{"total":269215,"free":25539,"allocated":243676,"largest_block":8692},"psram":{"total":8359824,"free":7595160,"allocated":764664,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":335737}}} +{"time":"2026-09-28T10:30:05.181Z","stage":"round5_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544584,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524344,"allocated":835064,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":338759}}} +{"time":"2026-09-28T10:30:05.360Z","stage":"round5_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544584,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524344,"allocated":835064,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":339050}}} +{"time":"2026-09-28T10:30:05.637Z","stage":"round5_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7614940,"min_free_heap":7469732,"internal":{"total":269167,"free":25223,"allocated":243944,"largest_block":8692},"psram":{"total":8359712,"free":7593732,"allocated":765980,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":339344}}} +{"time":"2026-09-28T10:30:06.377Z","stage":"round6_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616452,"min_free_heap":7469732,"internal":{"total":269215,"free":25535,"allocated":243680,"largest_block":8692},"psram":{"total":8359808,"free":7594936,"allocated":764872,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":339938}}} +{"time":"2026-09-28T10:30:09.453Z","stage":"round6_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3644,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544620,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524384,"allocated":835024,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":343038}}} +{"time":"2026-09-28T10:30:09.622Z","stage":"round6_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":760,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3644,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7543832,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359392,"free":7523596,"allocated":835796,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":343285}}} +{"time":"2026-09-28T10:30:09.871Z","stage":"round6_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7612656,"min_free_heap":7469732,"internal":{"total":269183,"free":25355,"allocated":243828,"largest_block":8692},"psram":{"total":8357344,"free":7587612,"allocated":769732,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":343446}}} +{"time":"2026-09-28T10:30:10.482Z","stage":"round7_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616452,"min_free_heap":7469732,"internal":{"total":269215,"free":25539,"allocated":243676,"largest_block":8692},"psram":{"total":8359808,"free":7594932,"allocated":764876,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":344059}}} +{"time":"2026-09-28T10:30:13.416Z","stage":"round7_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544636,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524396,"allocated":835012,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":346988}}} +{"time":"2026-09-28T10:30:13.574Z","stage":"round7_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544636,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524396,"allocated":835012,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":347266}}} +{"time":"2026-09-28T10:30:13.849Z","stage":"round7_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7615172,"min_free_heap":7469732,"internal":{"total":269183,"free":25355,"allocated":243828,"largest_block":8692},"psram":{"total":8359744,"free":7593832,"allocated":765912,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":347412}}} +{"time":"2026-09-28T10:30:14.451Z","stage":"round8_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616460,"min_free_heap":7469732,"internal":{"total":269215,"free":25535,"allocated":243680,"largest_block":8692},"psram":{"total":8359808,"free":7594944,"allocated":764864,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":348037}}} +{"time":"2026-09-28T10:30:17.439Z","stage":"round8_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544612,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524368,"allocated":835040,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":351029}}} +{"time":"2026-09-28T10:30:17.626Z","stage":"round8_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544612,"min_free_heap":7469732,"internal":{"total":268991,"free":24251,"allocated":244740,"largest_block":8692},"psram":{"total":8359408,"free":7524372,"allocated":835036,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":351282}}} +{"time":"2026-09-28T10:30:17.869Z","stage":"round8_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7615952,"min_free_heap":7469732,"internal":{"total":269183,"free":25355,"allocated":243828,"largest_block":8692},"psram":{"total":8359760,"free":7594616,"allocated":765144,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":351543}}} +{"time":"2026-09-28T10:30:18.574Z","stage":"round9_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7615300,"min_free_heap":7469732,"internal":{"total":269183,"free":25275,"allocated":243908,"largest_block":8692},"psram":{"total":8359680,"free":7594040,"allocated":765640,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":352165}}} +{"time":"2026-09-28T10:30:21.668Z","stage":"round9_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ssh_poll","priority":5,"stack_hwm":3996,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544608,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359408,"free":7524368,"allocated":835040,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":355244}}} +{"time":"2026-09-28T10:30:21.836Z","stage":"round9_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ssh_poll","priority":5,"stack_hwm":3996,"core":2147483647,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544608,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359408,"free":7524368,"allocated":835040,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":355513}}} +{"time":"2026-09-28T10:30:22.102Z","stage":"round9_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7615960,"min_free_heap":7469732,"internal":{"total":269183,"free":25359,"allocated":243824,"largest_block":8692},"psram":{"total":8359760,"free":7594620,"allocated":765140,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":355785}}} +{"time":"2026-09-28T10:30:22.832Z","stage":"round10_before","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616232,"min_free_heap":7469732,"internal":{"total":269215,"free":25539,"allocated":243676,"largest_block":8692},"psram":{"total":8359792,"free":7594712,"allocated":765080,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":356398}}} +{"time":"2026-09-28T10:30:25.700Z","stage":"round10_welcome","tasks":{"code":0,"data":{"tasks":[{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"ready"},{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7544628,"min_free_heap":7469732,"internal":{"total":268991,"free":24255,"allocated":244736,"largest_block":8692},"psram":{"total":8359408,"free":7524392,"allocated":835016,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":359271}}} +{"time":"2026-09-28T10:30:25.849Z","stage":"round10_input","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"ready"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"ssh_poll","priority":5,"stack_hwm":3984,"core":2147483647,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"}],"count":25}},"memory":{"code":0,"data":{"free_heap":7543692,"min_free_heap":7469732,"internal":{"total":268959,"free":23991,"allocated":244968,"largest_block":8692},"psram":{"total":8359296,"free":7523716,"allocated":835580,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":359550}}} +{"time":"2026-09-28T10:30:26.191Z","stage":"round10_closed","tasks":{"code":0,"data":{"tasks":[{"name":"httpd","priority":5,"stack_hwm":4200,"core":0,"state":"running"},{"name":"IDLE1","priority":0,"stack_hwm":728,"core":1,"state":"ready"},{"name":"IDLE0","priority":0,"stack_hwm":864,"core":0,"state":"ready"},{"name":"power_monitor","priority":5,"stack_hwm":1760,"core":0,"state":"blocked"},{"name":"ts_auto","priority":5,"stack_hwm":1828,"core":1,"state":"blocked"},{"name":"tiT","priority":18,"stack_hwm":1144,"core":2147483647,"state":"blocked"},{"name":"power_policy","priority":5,"stack_hwm":760,"core":0,"state":"blocked"},{"name":"websocket_task","priority":5,"stack_hwm":992,"core":2147483647,"state":"blocked"},{"name":"action_exec","priority":5,"stack_hwm":12804,"core":2147483647,"state":"blocked"},{"name":"w5500_tsk","priority":15,"stack_hwm":2468,"core":2147483647,"state":"blocked"},{"name":"https_coord","priority":5,"stack_hwm":5292,"core":2147483647,"state":"blocked"},{"name":"main","priority":1,"stack_hwm":188,"core":0,"state":"blocked"},{"name":"sio_agx-info","priority":5,"stack_hwm":1864,"core":2147483647,"state":"blocked"},{"name":"httpd","priority":5,"stack_hwm":15116,"core":2147483647,"state":"blocked"},{"name":"ts_event","priority":5,"stack_hwm":668,"core":2147483647,"state":"blocked"},{"name":"esp_timer","priority":22,"stack_hwm":2416,"core":0,"state":"suspended"},{"name":"ipc1","priority":24,"stack_hwm":408,"core":1,"state":"suspended"},{"name":"ts_console","priority":5,"stack_hwm":1788,"core":2147483647,"state":"blocked"},{"name":"ipc0","priority":24,"stack_hwm":128,"core":0,"state":"suspended"},{"name":"ws_telemetry","priority":2,"stack_hwm":1844,"core":1,"state":"suspended"},{"name":"led_render","priority":5,"stack_hwm":1164,"core":0,"state":"blocked"},{"name":"sys_evt","priority":20,"stack_hwm":1452,"core":0,"state":"blocked"},{"name":"dhcp_evt","priority":5,"stack_hwm":696,"core":2147483647,"state":"blocked"},{"name":"Tmr Svc","priority":1,"stack_hwm":544,"core":2147483647,"state":"blocked"}],"count":24}},"memory":{"code":0,"data":{"free_heap":7616184,"min_free_heap":7469732,"internal":{"total":269183,"free":25359,"allocated":243824,"largest_block":8692},"psram":{"total":8359776,"free":7594840,"allocated":764936,"largest_block":7471092}}},"info":{"code":0,"data":{"app":{"name":"TianShanOS","version":"0.5.2+3a19128d.09281801","idf_version":"v5.5.2","compile_time":"18:02:03","compile_date":"Sep 28 2026"},"chip":{"model":"ESP32-S3","cores":2,"revision":2,"features":["WiFi","BLE"]},"flash_size":16777216,"uptime_ms":359879}}} diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/final-idle.json b/docs/repair/ssh-poll-stack/device-diagnostic/final-idle.json new file mode 100644 index 0000000..93626fb --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/final-idle.json @@ -0,0 +1,222 @@ +{ + "stage": "final_idle", + "time": "2026-09-28T18:30:57.920294", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 4200, + "core": 0, + "state": "running" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 728, + "core": 1, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 864, + "core": 0, + "state": "ready" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 1828, + "core": 1, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 12804, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1144, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1864, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 760, + "core": 0, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 992, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2468, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5292, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 188, + "core": 0, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1760, + "core": 0, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 408, + "core": 1, + "state": "suspended" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1788, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 128, + "core": 0, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 696, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 1844, + "core": 1, + "state": "suspended" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 668, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2416, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1164, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1452, + "core": 0, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 544, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15116, + "core": 2147483647, + "state": "blocked" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7616896, + "min_free_heap": 7469732, + "internal": { + "total": 269231, + "free": 25671, + "allocated": 243560, + "largest_block": 8692 + }, + "psram": { + "total": 8359856, + "free": 7595232, + "allocated": 764624, + "largest_block": 7471092 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:02:03", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 391495 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/flash.log b/docs/repair/ssh-poll-stack/device-diagnostic/flash.log new file mode 100644 index 0000000..892f434 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/flash.log @@ -0,0 +1,239 @@ +Checking "python3" ... +Python 3.12.4 +"python3" has been detected +Activating ESP-IDF 5.5 +Setting IDF_PATH to '/Users/massif/esp/v5.5.2/esp-idf'. +* Checking python version ... 3.12.4 +* Checking python dependencies ... OK +* Deactivating the current ESP-IDF environment (if any) ... OK +* Establishing a new ESP-IDF environment ... OK +* Identifying shell ... zsh +* Detecting outdated tools in system ... Found tools that are not used by active ESP-IDF version. +For removing old versions of riscv32-esp-elf, cmake, xtensa-esp-elf, openocd-esp32, esp-rom-elfs, xtensa-esp-elf-gdb, riscv32-esp-elf-gdb use command 'python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall' +To free up even more space, remove installation packages of those tools. +Use option python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall --remove-archives. +* Shell completion ... Autocompletion code generated + +Done! You can now compile ESP-IDF projects. +Go to the project directory and run: + + idf.py build +Executing action: flash +Running ninja in directory /private/tmp/tianshan-ssh-stack-diagnostic/build +Executing "ninja flash"... +[1/6] cd /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ssh-stack-diagnostic/build/partition_table/partition-table.bin /tmp/tianshan-ssh-stack-diagnostic/build/TianShanOS.bin +TianShanOS.bin binary size 0x259ee0 bytes. Smallest app partition is 0x300000 bytes. 0xa6120 bytes (22%) free. +[2/6] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-ssh-stack-diagnostic/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ssh-stack-diagnostic/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[3/6] No install step for 'bootloader' +[4/6] cd /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ssh-stack-diagnostic/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[5/6] Completed 'bootloader' +[5/6] cd /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py && /Users/massif/.espressif/tools/cmake/3.30.2/CMake.app/Contents/bin/cmake -D IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf -D "SERIAL_TOOL=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python;;/Users/massif/esp/v5.5.2/esp-idf/components/esptool_py/esptool/esptool.py;--chip;esp32s3" -D "SERIAL_TOOL_ARGS=--before=default_reset;--after=hard_reset;write_flash;@flash_args" -D WORKING_DIRECTORY=/tmp/tianshan-ssh-stack-diagnostic/build -P /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py/run_serial_tool.cmake +esptool.py --chip esp32s3 -p /dev/cu.usbmodem11401 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x20000 TianShanOS.bin 0x8000 partition_table/partition-table.bin 0x16000 ota_data_initial.bin 0x6a0000 www.bin +esptool.py v4.12.dev2 +Serial port /dev/cu.usbmodem11401 +Connecting... +Chip is ESP32-S3 (QFN56) (revision v0.2) +Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3) +Crystal is 40MHz +USB mode: USB-Serial/JTAG +MAC: 20:6e:f1:a1:d5:8c +Uploading stub... +Running stub... +Stub running... +Changing baud rate to 460800 +Changed. +Configuring flash size... +Flash will be erased from 0x00000000 to 0x00005fff... +Flash will be erased from 0x00020000 to 0x00279fff... +Flash will be erased from 0x00008000 to 0x00008fff... +Flash will be erased from 0x00016000 to 0x00017fff... +Flash will be erased from 0x006a0000 to 0x0099ffff... +SHA digest in image updated +Compressed 22496 bytes to 14267... +Writing at 0x00000000... (100 %) +Wrote 22496 bytes (14267 compressed) at 0x00000000 in 0.2 seconds (effective 775.8 kbit/s)... +Hash of data verified. +Compressed 2465504 bytes to 1372560... +Writing at 0x00020000... (1 %) +Writing at 0x0002d702... (2 %) +Writing at 0x0003a713... (3 %) +Writing at 0x0004847c... (4 %) +Writing at 0x00055279... (5 %) +Writing at 0x00063d1c... (7 %) +Writing at 0x00072811... (8 %) +Writing at 0x000810b4... (9 %) +Writing at 0x0008cd04... (10 %) +Writing at 0x00091c7a... (11 %) +Writing at 0x00097b74... (13 %) +Writing at 0x0009c711... (14 %) +Writing at 0x000a1538... (15 %) +Writing at 0x000a68e5... (16 %) +Writing at 0x000ae7c4... (17 %) +Writing at 0x000ba649... (19 %) +Writing at 0x000c1735... (20 %) +Writing at 0x000c83e3... (21 %) +Writing at 0x000cf65d... (22 %) +Writing at 0x000d6e13... (23 %) +Writing at 0x000ddabd... (25 %) +Writing at 0x000e4342... (26 %) +Writing at 0x000eadd0... (27 %) +Writing at 0x000f0fdf... (28 %) +Writing at 0x000f75d6... (29 %) +Writing at 0x000fd828... (30 %) +Writing at 0x001039ca... (32 %) +Writing at 0x0010a632... (33 %) +Writing at 0x0011055b... (34 %) +Writing at 0x00116585... (35 %) +Writing at 0x0011c8f9... (36 %) +Writing at 0x00122ea4... (38 %) +Writing at 0x00129b06... (39 %) +Writing at 0x0013090c... (40 %) +Writing at 0x00136f8e... (41 %) +Writing at 0x0013d288... (42 %) +Writing at 0x00143b55... (44 %) +Writing at 0x0014a0a8... (45 %) +Writing at 0x0015022e... (46 %) +Writing at 0x00156c57... (47 %) +Writing at 0x0015d8f6... (48 %) +Writing at 0x001644e1... (50 %) +Writing at 0x0016b16a... (51 %) +Writing at 0x00171a88... (52 %) +Writing at 0x00178193... (53 %) +Writing at 0x0017f293... (54 %) +Writing at 0x001857e8... (55 %) +Writing at 0x0018be96... (57 %) +Writing at 0x001923c3... (58 %) +Writing at 0x00199906... (59 %) +Writing at 0x0019fb5e... (60 %) +Writing at 0x001a646d... (61 %) +Writing at 0x001ad231... (63 %) +Writing at 0x001b47e1... (64 %) +Writing at 0x001bb1fa... (65 %) +Writing at 0x001c19dd... (66 %) +Writing at 0x001c7c21... (67 %) +Writing at 0x001cdfb0... (69 %) +Writing at 0x001d4467... (70 %) +Writing at 0x001daa16... (71 %) +Writing at 0x001e180c... (72 %) +Writing at 0x001e8387... (73 %) +Writing at 0x001eee3a... (75 %) +Writing at 0x001f5c18... (76 %) +Writing at 0x001fc685... (77 %) +Writing at 0x0020304e... (78 %) +Writing at 0x00209456... (79 %) +Writing at 0x0021047a... (80 %) +Writing at 0x00216ab8... (82 %) +Writing at 0x0021d992... (83 %) +Writing at 0x00223943... (84 %) +Writing at 0x002289a2... (85 %) +Writing at 0x0022dfab... (86 %) +Writing at 0x002333b2... (88 %) +Writing at 0x00238cf0... (89 %) +Writing at 0x0023f567... (90 %) +Writing at 0x00245a2d... (91 %) +Writing at 0x0024b042... (92 %) +Writing at 0x0025310a... (94 %) +Writing at 0x00259419... (95 %) +Writing at 0x002601eb... (96 %) +Writing at 0x00266ebb... (97 %) +Writing at 0x0026d78a... (98 %) +Writing at 0x00274821... (100 %) +Wrote 2465504 bytes (1372560 compressed) at 0x00020000 in 12.7 seconds (effective 1554.2 kbit/s)... +Hash of data verified. +Compressed 3072 bytes to 180... +Writing at 0x00008000... (100 %) +Wrote 3072 bytes (180 compressed) at 0x00008000 in 0.0 seconds (effective 738.0 kbit/s)... +Hash of data verified. +Compressed 8192 bytes to 31... +Writing at 0x00016000... (100 %) +Wrote 8192 bytes (31 compressed) at 0x00016000 in 0.0 seconds (effective 1397.2 kbit/s)... +Hash of data verified. +Compressed 3145728 bytes to 1301907... +Writing at 0x006a0000... (1 %) +Writing at 0x006a457e... (2 %) +Writing at 0x006a89e3... (3 %) +Writing at 0x006b047c... (5 %) +Writing at 0x006baf69... (6 %) +Writing at 0x006d1206... (7 %) +Writing at 0x006da3ed... (8 %) +Writing at 0x006def13... (10 %) +Writing at 0x006e398f... (11 %) +Writing at 0x006e81c3... (12 %) +Writing at 0x006ec7fd... (13 %) +Writing at 0x006f0d22... (15 %) +Writing at 0x006f5a46... (16 %) +Writing at 0x006faa98... (17 %) +Writing at 0x006fefab... (18 %) +Writing at 0x007035af... (20 %) +Writing at 0x007082a8... (21 %) +Writing at 0x0070c80f... (22 %) +Writing at 0x007122f1... (23 %) +Writing at 0x007195c7... (25 %) +Writing at 0x0071e795... (26 %) +Writing at 0x00724b4d... (27 %) +Writing at 0x00729ad6... (28 %) +Writing at 0x0072de98... (30 %) +Writing at 0x00732372... (31 %) +Writing at 0x00736749... (32 %) +Writing at 0x0073ab18... (33 %) +Writing at 0x0073eee3... (35 %) +Writing at 0x007433b1... (36 %) +Writing at 0x007477a8... (37 %) +Writing at 0x0074bb76... (38 %) +Writing at 0x0074ff3f... (40 %) +Writing at 0x0075447a... (41 %) +Writing at 0x0075c5f8... (42 %) +Writing at 0x00769000... (43 %) +Writing at 0x00778601... (45 %) +Writing at 0x00789b0f... (46 %) +Writing at 0x0079ac96... (47 %) +Writing at 0x007af271... (48 %) +Writing at 0x007bf6f8... (50 %) +Writing at 0x007d0f1b... (51 %) +Writing at 0x007e45da... (52 %) +Writing at 0x007f75ac... (53 %) +Writing at 0x00807e03... (55 %) +Writing at 0x0081a13e... (56 %) +Writing at 0x0082d777... (57 %) +Writing at 0x0083fde1... (58 %) +Writing at 0x0085163b... (60 %) +Writing at 0x0085ee5a... (61 %) +Writing at 0x0086c200... (62 %) +Writing at 0x008775dc... (63 %) +Writing at 0x00883eaf... (65 %) +Writing at 0x008903ff... (66 %) +Writing at 0x00897717... (67 %) +Writing at 0x0089ba87... (68 %) +Writing at 0x0089feb5... (70 %) +Writing at 0x008a4410... (71 %) +Writing at 0x008a884e... (72 %) +Writing at 0x008acbf6... (73 %) +Writing at 0x008b17d0... (75 %) +Writing at 0x008b5b99... (76 %) +Writing at 0x008b9f62... (77 %) +Writing at 0x008be429... (78 %) +Writing at 0x008c27e8... (80 %) +Writing at 0x008c6bba... (81 %) +Writing at 0x008caf7b... (82 %) +Writing at 0x008cf43f... (83 %) +Writing at 0x008d3802... (85 %) +Writing at 0x008d7bc6... (86 %) +Writing at 0x008dbf87... (87 %) +Writing at 0x008e0a43... (88 %) +Writing at 0x008e6b82... (90 %) +Writing at 0x008eaf45... (91 %) +Writing at 0x008ef3fe... (92 %) +Writing at 0x008f3873... (93 %) +Writing at 0x008fc62d... (95 %) +Writing at 0x0090dc54... (96 %) +Writing at 0x0091db75... (97 %) +Writing at 0x0092f6a7... (98 %) +Writing at 0x0093dbfb... (100 %) +Wrote 3145728 bytes (1301907 compressed) at 0x006a0000 in 14.5 seconds (effective 1739.0 kbit/s)... +Hash of data verified. + +Leaving... +Hard resetting via RTS pin... +Done diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/output-input-resize.json b/docs/repair/ssh-poll-stack/device-diagnostic/output-input-resize.json new file mode 100644 index 0000000..5e3ef97 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/output-input-resize.json @@ -0,0 +1,229 @@ +{ + "stage": "output_input_resize", + "time": "2026-09-28T18:25:56.788651", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 4200, + "core": 0, + "state": "running" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 760, + "core": 1, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 864, + "core": 0, + "state": "ready" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1944, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 1828, + "core": 1, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1760, + "core": 0, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 12804, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1144, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 992, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 760, + "core": 0, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2468, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5292, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 188, + "core": 0, + "state": "blocked" + }, + { + "name": "ssh_poll", + "priority": 5, + "stack_hwm": 3984, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 544, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15116, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1788, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 128, + "core": 0, + "state": "suspended" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 696, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 668, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2416, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1164, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1452, + "core": 0, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 408, + "core": 1, + "state": "suspended" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 1844, + "core": 1, + "state": "suspended" + } + ], + "count": 25 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7546440, + "min_free_heap": 7469732, + "internal": { + "total": 269023, + "free": 24431, + "allocated": 244592, + "largest_block": 8692 + }, + "psram": { + "total": 8359536, + "free": 7526028, + "allocated": 833508, + "largest_block": 7471092 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:02:03", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 90494 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round1-closed.json b/docs/repair/ssh-poll-stack/device-diagnostic/round1-closed.json new file mode 100644 index 0000000..1c05825 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round1-closed.json @@ -0,0 +1,222 @@ +{ + "stage": "round1_closed_local_help", + "time": "2026-09-28T18:26:47.357001", + "tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 4200, + "core": 0, + "state": "running" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1164, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 760, + "core": 1, + "state": "ready" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 864, + "core": 0, + "state": "ready" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1144, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1760, + "core": 0, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1928, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 992, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 760, + "core": 0, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 12804, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2468, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5292, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 188, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 1828, + "core": 1, + "state": "blocked" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 696, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 408, + "core": 1, + "state": "suspended" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 1844, + "core": 1, + "state": "suspended" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 544, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15116, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 668, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2416, + "core": 0, + "state": "suspended" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1452, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1788, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 128, + "core": 0, + "state": "suspended" + } + ], + "count": 24 + } + }, + "memory": { + "code": 0, + "data": { + "free_heap": 7618496, + "min_free_heap": 7469732, + "internal": { + "total": 269231, + "free": 25671, + "allocated": 243560, + "largest_block": 8692 + }, + "psram": { + "total": 8359968, + "free": 7596844, + "allocated": 763124, + "largest_block": 7471092 + } + } + }, + "info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:02:03", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 140957 + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round10-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round10-automatic.json new file mode 100644 index 0000000..9fabb3f --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round10-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 10, + "minimumObservedHwm": 3984, + "free_heap": 7616184, + "psram_free": 7594840, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round2-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round2-automatic.json new file mode 100644 index 0000000..55b8f2b --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round2-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 2, + "minimumObservedHwm": 3984, + "free_heap": 7617308, + "psram_free": 7595964, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round3-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round3-automatic.json new file mode 100644 index 0000000..e7e233b --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round3-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 3, + "minimumObservedHwm": 3996, + "free_heap": 7616864, + "psram_free": 7595524, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round4-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round4-automatic.json new file mode 100644 index 0000000..3059967 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round4-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 4, + "minimumObservedHwm": 3984, + "free_heap": 7616384, + "psram_free": 7595044, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round5-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round5-automatic.json new file mode 100644 index 0000000..d1200d0 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round5-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 5, + "minimumObservedHwm": 3984, + "free_heap": 7614940, + "psram_free": 7593732, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round6-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round6-automatic.json new file mode 100644 index 0000000..07aa809 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round6-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 6, + "minimumObservedHwm": 3644, + "free_heap": 7612656, + "psram_free": 7587612, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round7-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round7-automatic.json new file mode 100644 index 0000000..115b67f --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round7-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 7, + "minimumObservedHwm": 3984, + "free_heap": 7615172, + "psram_free": 7593832, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round8-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round8-automatic.json new file mode 100644 index 0000000..758ef63 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round8-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 8, + "minimumObservedHwm": 3984, + "free_heap": 7615952, + "psram_free": 7594616, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/round9-automatic.json b/docs/repair/ssh-poll-stack/device-diagnostic/round9-automatic.json new file mode 100644 index 0000000..cc8b2c1 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/round9-automatic.json @@ -0,0 +1,14 @@ +{ + "round": 9, + "minimumObservedHwm": 3996, + "free_heap": 7615960, + "psram_free": 7594620, + "statuses": [ + "connecting", + "connected", + "disconnecting", + "closed" + ], + "echoVerified": true, + "pollerGone": true +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/rounds.mjs b/docs/repair/ssh-poll-stack/device-diagnostic/rounds.mjs new file mode 100644 index 0000000..cce7990 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/rounds.mjs @@ -0,0 +1,39 @@ +import fs from 'node:fs'; +const dir='/tmp/tianshan-ssh-stack-diagnostic',base='http://10.10.99.97'; +const password=process.env.TS_TEST_PASSWORD;if(!password)throw Error('Missing credential'); +const sleep=ms=>new Promise(r=>setTimeout(r,ms)); +async function snapshot(stage){let r={time:new Date().toISOString(),stage};for(const n of ['tasks','memory','info']){const a=await fetch(base+'/api/v1/system/'+n,{signal:AbortSignal.timeout(5000)});r[n]=await a.json();if(r[n].code!==0)throw Error('API failure '+n);}fs.appendFileSync(dir+'/automatic-samples.jsonl',JSON.stringify(r)+'\n');return r;} +const pollers=r=>r.tasks.data.tasks.filter(t=>t.name==='ssh_poll'); +function faults(){return fs.readFileSync(dir+'/serial.log','utf8').split('\n').filter(l=>/stack overflow|stack canary|Guru Meditation|CORRUPT HEAP|assert failed|watchdog|heap poisoning|LoadProhibited|StoreProhibited|Unhandled debug exception|stack smashing/i.test(l));} +for(let round=2;round<=10;round++){ + const before=await snapshot('round'+round+'_before');if(pollers(before).length)throw Error('Existing SSH task: stop without takeover'); + let messages=[],output='',connected=false,closed=false,err=null; + const ws=new WebSocket('ws://10.10.99.97/ws'); + ws.addEventListener('message',e=>{try{let m=JSON.parse(e.data);messages.push(m);if(m.type==='ssh_output'){output+=m.data||'';fs.appendFileSync(dir+'/output-round'+round+'.txt',m.data||'');}if(m.type==='ssh_status'){if(m.status==='connected')connected=true;if(m.status==='closed')closed=true;if(m.status==='error')err=Error(m.message);}if(m.type==='error')err=Error(m.message||m.error);}catch(e){err=e;}}); + ws.addEventListener('error',()=>{err=Error('WebSocket error');}); + async function wait(fn,ms=15000){const end=Date.now()+ms;while(!fn()){if(err)throw err;if(Date.now()>end)throw Error('Stage timed out; no command retry');await sleep(50);}} + const send=m=>ws.send(JSON.stringify(m)); + try{ + await wait(()=>ws.readyState===1); + send({type:'ssh_connect',host:'10.10.99.98',port:22,user:'rm01',password}); + await wait(()=>connected);await wait(()=>/rm01@agx:.*\$/.test(output)); + const welcome=await snapshot('round'+round+'_welcome');if(pollers(welcome).length!==1)throw Error('Wrong poller count'); + output='';const marker='TIANSHAN_DIAG_VERIFIED_'+round; + send({type:'ssh_input',data:"echo '"+marker+"'\r"}); + await wait(()=>output.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g,'').split(/\r?\n/).some(l=>l.trim()===marker)); + const active=await snapshot('round'+round+'_input');if(pollers(active).some(t=>t.stack_hwm<2048))throw Error('Insufficient stack margin'); + send({type:'ssh_disconnect'});await wait(()=>closed); + let after; + for(let i=0;i<20;i++){after=await snapshot('round'+round+'_closed');if(!pollers(after).length)break;await sleep(100);} + if(pollers(after).length)throw Error('Poller not reclaimed'); + if(after.info.data.uptime_mst.stack_hwm),...pollers(active).map(t=>t.stack_hwm)),free_heap:after.memory.data.free_heap,psram_free:after.memory.data.psram.free,statuses:messages.filter(m=>m.type==='ssh_status').map(m=>m.status),echoVerified:true,pollerGone:true}; + fs.writeFileSync(dir+'/round'+round+'-automatic.json',JSON.stringify(result,null,2));console.log(JSON.stringify(result)); + }finally{ + if(connected&&!closed&&ws.readyState===1){send({type:'ssh_disconnect'});await sleep(1000);} + ws.close(); + } + await sleep(500); +} +console.log('NINE_AUTOMATIC_ROUNDS_COMPLETE'); diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/samples.jsonl b/docs/repair/ssh-poll-stack/device-diagnostic/samples.jsonl new file mode 100644 index 0000000..d69e93c --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/samples.jsonl @@ -0,0 +1,172 @@ +{"time": "2026-09-28T18:24:43.361228", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1244, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2612, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619644, "min_free_heap": 7473908, "internal": {"total": 269455, "free": 26439, "allocated": 243016, "largest_block": 8692}, "psram": {"total": 8360080, "free": 7597212, "allocated": 762868, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 16926}}} +{"time": "2026-09-28T18:24:45.457589", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1244, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2612, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618500, "min_free_heap": 7473908, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360016, "free": 7596448, "allocated": 763568, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 19119}}} +{"time": "2026-09-28T18:24:47.649068", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1244, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2612, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619976, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597684, "allocated": 762364, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 21199}}} +{"time": "2026-09-28T18:24:49.727677", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1212, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619976, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597684, "allocated": 762364, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 23279}}} +{"time": "2026-09-28T18:24:51.810611", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1212, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619984, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597684, "allocated": 762364, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 25362}}} +{"time": "2026-09-28T18:24:53.892582", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1212, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619980, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597688, "allocated": 762360, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 27447}}} +{"time": "2026-09-28T18:24:55.975923", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1192, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619984, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597684, "allocated": 762364, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 29532}}} +{"time": "2026-09-28T18:24:58.056995", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1192, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619976, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597684, "allocated": 762364, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 31607}}} +{"time": "2026-09-28T18:25:00.135212", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4664, "core": 2147483647, "state": "running"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1192, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 3716, "core": 2147483647, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7619976, "min_free_heap": 7472928, "internal": {"total": 269439, "free": 26307, "allocated": 243132, "largest_block": 8692}, "psram": {"total": 8360048, "free": 7597684, "allocated": 762364, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 33690}}} +{"time": "2026-09-28T18:25:02.215777", "tasks": {"error": "timed out"}, "memory": {"code": 0, "data": {"free_heap": 7615860, "min_free_heap": 7472928, "internal": {"total": 269343, "free": 25503, "allocated": 243840, "largest_block": 8692}, "psram": {"total": 8359664, "free": 7594324, "allocated": 765340, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 40230}}} +{"time": "2026-09-28T18:25:08.760992", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617308, "min_free_heap": 7472784, "internal": {"total": 269199, "free": 25323, "allocated": 243876, "largest_block": 8692}, "psram": {"total": 8359840, "free": 7596000, "allocated": 763840, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 42549}}} +{"time": "2026-09-28T18:25:11.094871", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616788, "min_free_heap": 7472684, "internal": {"total": 269183, "free": 25191, "allocated": 243992, "largest_block": 8692}, "psram": {"total": 8359792, "free": 7595600, "allocated": 764192, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 44708}}} +{"time": "2026-09-28T18:25:13.260769", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617372, "min_free_heap": 7472684, "internal": {"total": 269167, "free": 25143, "allocated": 244024, "largest_block": 8692}, "psram": {"total": 8359824, "free": 7596244, "allocated": 763580, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 46835}}} +{"time": "2026-09-28T18:25:15.386659", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616584, "min_free_heap": 7472684, "internal": {"total": 269167, "free": 25143, "allocated": 244024, "largest_block": 8692}, "psram": {"total": 8359808, "free": 7595456, "allocated": 764352, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 48995}}} +{"time": "2026-09-28T18:25:17.529635", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617360, "min_free_heap": 7472684, "internal": {"total": 269167, "free": 25143, "allocated": 244024, "largest_block": 8692}, "psram": {"total": 8359824, "free": 7596232, "allocated": 763592, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 51125}}} +{"time": "2026-09-28T18:25:19.664782", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617372, "min_free_heap": 7472684, "internal": {"total": 269167, "free": 25143, "allocated": 244024, "largest_block": 8692}, "psram": {"total": 8359824, "free": 7596244, "allocated": 763580, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 53255}}} +{"time": "2026-09-28T18:25:21.808339", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617380, "min_free_heap": 7472684, "internal": {"total": 269167, "free": 25143, "allocated": 244024, "largest_block": 8692}, "psram": {"total": 8359824, "free": 7596252, "allocated": 763572, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 55410}}} +{"time": "2026-09-28T18:25:23.941214", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4524, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617372, "min_free_heap": 7472684, "internal": {"total": 269167, "free": 25143, "allocated": 244024, "largest_block": 8692}, "psram": {"total": 8359824, "free": 7596244, "allocated": 763580, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 57556}}} +{"time": "2026-09-28T18:25:26.086622", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4044, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545084, "min_free_heap": 7472684, "internal": {"total": 268975, "free": 24035, "allocated": 244940, "largest_block": 8692}, "psram": {"total": 8359392, "free": 7525060, "allocated": 834332, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 59807}}} +{"time": "2026-09-28T18:25:28.339002", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "ready"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544296, "min_free_heap": 7472684, "internal": {"total": 268975, "free": 24035, "allocated": 244940, "largest_block": 8692}, "psram": {"total": 8359376, "free": 7524280, "allocated": 835096, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 62035}}} +{"time": "2026-09-28T18:25:30.565226", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545088, "min_free_heap": 7472684, "internal": {"total": 268975, "free": 24035, "allocated": 244940, "largest_block": 8692}, "psram": {"total": 8359392, "free": 7525068, "allocated": 834324, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 64251}}} +{"time": "2026-09-28T18:25:32.785421", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545080, "min_free_heap": 7469732, "internal": {"total": 268975, "free": 24035, "allocated": 244940, "largest_block": 8692}, "psram": {"total": 8359392, "free": 7525060, "allocated": 834332, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 66471}}} +{"time": "2026-09-28T18:25:35.019632", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545092, "min_free_heap": 7469732, "internal": {"total": 268975, "free": 24035, "allocated": 244940, "largest_block": 8692}, "psram": {"total": 8359392, "free": 7525072, "allocated": 834320, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 68693}}} +{"time": "2026-09-28T18:25:37.250535", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544908, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24167, "allocated": 244824, "largest_block": 8692}, "psram": {"total": 8359504, "free": 7525908, "allocated": 833596, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 70941}}} +{"time": "2026-09-28T18:25:39.470966", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546696, "min_free_heap": 7469732, "internal": {"total": 269023, "free": 24431, "allocated": 244592, "largest_block": 8692}, "psram": {"total": 8359568, "free": 7526284, "allocated": 833284, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 73145}}} +{"time": "2026-09-28T18:25:41.682125", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546684, "min_free_heap": 7469732, "internal": {"total": 269023, "free": 24431, "allocated": 244592, "largest_block": 8692}, "psram": {"total": 8359568, "free": 7526260, "allocated": 833308, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 75321}}} +{"time": "2026-09-28T18:25:43.863226", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546692, "min_free_heap": 7469732, "internal": {"total": 269023, "free": 24431, "allocated": 244592, "largest_block": 8692}, "psram": {"total": 8359568, "free": 7526280, "allocated": 833288, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 77530}}} +{"time": "2026-09-28T18:25:46.065845", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546696, "min_free_heap": 7469732, "internal": {"total": 269023, "free": 24431, "allocated": 244592, "largest_block": 8692}, "psram": {"total": 8359568, "free": 7526284, "allocated": 833284, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 79703}}} +{"time": "2026-09-28T18:25:48.243985", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 81891}}} +{"time": "2026-09-28T18:25:50.444961", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546364, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359600, "free": 7525820, "allocated": 833780, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 84039}}} +{"time": "2026-09-28T18:25:52.575184", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 86171}}} +{"time": "2026-09-28T18:25:54.709681", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 88308}}} +{"time": "2026-09-28T18:25:56.839626", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545988, "min_free_heap": 7469732, "internal": {"total": 269007, "free": 24299, "allocated": 244708, "largest_block": 8692}, "psram": {"total": 8359488, "free": 7525708, "allocated": 833780, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 90512}}} +{"time": "2026-09-28T18:25:59.042019", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 92657}}} +{"time": "2026-09-28T18:26:01.207606", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 94779}}} +{"time": "2026-09-28T18:26:03.308468", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 96902}}} +{"time": "2026-09-28T18:26:05.449396", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547148, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526604, "allocated": 833012, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 99020}}} +{"time": "2026-09-28T18:26:07.550013", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 101154}}} +{"time": "2026-09-28T18:26:09.701907", "tasks": {"code": 0, "data": {"tasks": [{"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547156, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526612, "allocated": 833004, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 103307}}} +{"time": "2026-09-28T18:26:11.841884", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 105442}}} +{"time": "2026-09-28T18:26:13.972682", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 107566}}} +{"time": "2026-09-28T18:26:16.124197", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 109707}}} +{"time": "2026-09-28T18:26:18.257782", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 111840}}} +{"time": "2026-09-28T18:26:20.379107", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547156, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526612, "allocated": 833004, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 113984}}} +{"time": "2026-09-28T18:26:22.529574", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1944, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 116120}}} +{"time": "2026-09-28T18:26:24.671503", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7547152, "min_free_heap": 7469732, "internal": {"total": 269039, "free": 24563, "allocated": 244476, "largest_block": 8692}, "psram": {"total": 8359616, "free": 7526608, "allocated": 833008, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 118267}}} +{"time": "2026-09-28T18:26:26.795938", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 120367}}} +{"time": "2026-09-28T18:26:28.907261", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 122501}}} +{"time": "2026-09-28T18:26:31.032762", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 124623}}} +{"time": "2026-09-28T18:26:33.167208", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 126735}}} +{"time": "2026-09-28T18:26:35.269284", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596844, "allocated": 763124, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 128866}}} +{"time": "2026-09-28T18:26:37.400051", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 130993}}} +{"time": "2026-09-28T18:26:39.539848", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617708, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359952, "free": 7596044, "allocated": 763908, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 133145}}} +{"time": "2026-09-28T18:26:41.670929", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596844, "allocated": 763124, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 135282}}} +{"time": "2026-09-28T18:26:43.820525", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596844, "allocated": 763124, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 137385}}} +{"time": "2026-09-28T18:26:45.936923", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 139515}}} +{"time": "2026-09-28T18:26:48.056484", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596844, "allocated": 763124, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 141642}}} +{"time": "2026-09-28T18:26:50.191489", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618492, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596828, "allocated": 763140, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 143795}}} +{"time": "2026-09-28T18:26:52.332260", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618492, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596828, "allocated": 763140, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 145932}}} +{"time": "2026-09-28T18:26:54.463877", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617708, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359952, "free": 7596056, "allocated": 763896, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 148074}}} +{"time": "2026-09-28T18:26:56.627667", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 150201}}} +{"time": "2026-09-28T18:26:58.752665", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618492, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596828, "allocated": 763140, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 152357}}} +{"time": "2026-09-28T18:27:00.894907", "tasks": {"code": 0, "data": {"tasks": [{"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "ready"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596844, "allocated": 763124, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 154492}}} +{"time": "2026-09-28T18:27:03.025736", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596844, "allocated": 763124, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 156625}}} +{"time": "2026-09-28T18:27:05.161077", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 158755}}} +{"time": "2026-09-28T18:27:07.294782", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 160871}}} +{"time": "2026-09-28T18:27:09.408075", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618496, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 162981}}} +{"time": "2026-09-28T18:27:11.520680", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1928, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 165116}}} +{"time": "2026-09-28T18:27:13.651957", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 167220}}} +{"time": "2026-09-28T18:27:15.765436", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 169370}}} +{"time": "2026-09-28T18:27:17.918142", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 171520}}} +{"time": "2026-09-28T18:27:20.062436", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 173641}}} +{"time": "2026-09-28T18:27:22.189406", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 175783}}} +{"time": "2026-09-28T18:27:24.335569", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618716, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597052, "allocated": 762932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 177930}}} +{"time": "2026-09-28T18:27:26.479435", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617936, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596272, "allocated": 763696, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 180090}}} +{"time": "2026-09-28T18:27:28.634489", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618720, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597068, "allocated": 762916, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 182205}}} +{"time": "2026-09-28T18:27:30.739632", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618720, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7597056, "allocated": 762928, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 184309}}} +{"time": "2026-09-28T18:27:32.839561", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 186417}}} +{"time": "2026-09-28T18:27:34.968811", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 188541}}} +{"time": "2026-09-28T18:27:37.088804", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 190665}}} +{"time": "2026-09-28T18:27:39.222385", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597280, "allocated": 762720, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 192793}}} +{"time": "2026-09-28T18:27:41.346184", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 194929}}} +{"time": "2026-09-28T18:27:43.482502", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597288, "allocated": 762712, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 197073}}} +{"time": "2026-09-28T18:27:45.607429", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618156, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7596492, "allocated": 763492, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 199196}}} +{"time": "2026-09-28T18:27:47.748836", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618932, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597268, "allocated": 762732, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 201345}}} +{"time": "2026-09-28T18:27:49.897922", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 203476}}} +{"time": "2026-09-28T18:27:52.024736", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 205598}}} +{"time": "2026-09-28T18:27:54.147321", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618948, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597284, "allocated": 762716, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 207711}}} +{"time": "2026-09-28T18:27:56.258877", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597280, "allocated": 762720, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 209842}}} +{"time": "2026-09-28T18:27:58.392727", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618948, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597284, "allocated": 762716, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 211973}}} +{"time": "2026-09-28T18:28:00.507146", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7615892, "min_free_heap": 7469732, "internal": {"total": 269215, "free": 25603, "allocated": 243612, "largest_block": 8692}, "psram": {"total": 8358672, "free": 7593128, "allocated": 765544, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 214104}}} +{"time": "2026-09-28T18:28:02.658627", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618140, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7596476, "allocated": 763508, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 216233}}} +{"time": "2026-09-28T18:28:04.786352", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597288, "allocated": 762712, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 218378}}} +{"time": "2026-09-28T18:28:06.915316", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 220499}}} +{"time": "2026-09-28T18:28:09.047748", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618936, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597272, "allocated": 762728, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 222611}}} +{"time": "2026-09-28T18:28:11.156966", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 224745}}} +{"time": "2026-09-28T18:28:13.297448", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597276, "allocated": 762724, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 226888}}} +{"time": "2026-09-28T18:28:15.430380", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618936, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597272, "allocated": 762728, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 229042}}} +{"time": "2026-09-28T18:28:17.577652", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618928, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597264, "allocated": 762736, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 231187}}} +{"time": "2026-09-28T18:28:19.723644", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597288, "allocated": 762712, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 233325}}} +{"time": "2026-09-28T18:28:21.859654", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 235463}}} +{"time": "2026-09-28T18:28:24.010868", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 237600}}} +{"time": "2026-09-28T18:28:26.133353", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597280, "allocated": 762720, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 239713}}} +{"time": "2026-09-28T18:28:28.266592", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 241838}}} +{"time": "2026-09-28T18:28:30.387582", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 243954}}} +{"time": "2026-09-28T18:28:32.504937", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 246100}}} +{"time": "2026-09-28T18:28:34.647639", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597280, "allocated": 762720, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 248247}}} +{"time": "2026-09-28T18:28:36.778232", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597280, "allocated": 762720, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 250385}}} +{"time": "2026-09-28T18:28:38.938433", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597276, "allocated": 762724, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 252539}}} +{"time": "2026-09-28T18:28:41.071131", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597276, "allocated": 762724, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 254653}}} +{"time": "2026-09-28T18:28:43.206609", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 256801}}} +{"time": "2026-09-28T18:28:45.331975", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 258941}}} +{"time": "2026-09-28T18:28:47.476345", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618944, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597292, "allocated": 762708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 261063}}} +{"time": "2026-09-28T18:28:49.605075", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618152, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359984, "free": 7596488, "allocated": 763496, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 263215}}} +{"time": "2026-09-28T18:28:51.749940", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618940, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8360000, "free": 7597276, "allocated": 762724, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 265350}}} +{"time": "2026-09-28T18:28:53.880214", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4056, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546444, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8359536, "free": 7526204, "allocated": 833332, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 267457}}} +{"time": "2026-09-28T18:28:56.007222", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546000, "min_free_heap": 7469732, "internal": {"total": 268975, "free": 24123, "allocated": 244852, "largest_block": 8692}, "psram": {"total": 8359488, "free": 7525892, "allocated": 833596, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 269613}}} +{"time": "2026-09-28T18:28:58.149868", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546000, "min_free_heap": 7469732, "internal": {"total": 268975, "free": 24123, "allocated": 244852, "largest_block": 8692}, "psram": {"total": 8359488, "free": 7525888, "allocated": 833600, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 271756}}} +{"time": "2026-09-28T18:29:00.296297", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546896, "min_free_heap": 7469732, "internal": {"total": 269007, "free": 24387, "allocated": 244620, "largest_block": 8692}, "psram": {"total": 8359584, "free": 7526524, "allocated": 833060, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 273892}}} +{"time": "2026-09-28T18:29:02.421308", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546896, "min_free_heap": 7469732, "internal": {"total": 269007, "free": 24387, "allocated": 244620, "largest_block": 8692}, "psram": {"total": 8359584, "free": 7526528, "allocated": 833056, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 276012}}} +{"time": "2026-09-28T18:29:04.564898", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546896, "min_free_heap": 7469732, "internal": {"total": 269007, "free": 24387, "allocated": 244620, "largest_block": 8692}, "psram": {"total": 8359584, "free": 7526524, "allocated": 833060, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 278151}}} +{"time": "2026-09-28T18:29:06.705482", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546108, "min_free_heap": 7469732, "internal": {"total": 269007, "free": 24387, "allocated": 244620, "largest_block": 8692}, "psram": {"total": 8359568, "free": 7525736, "allocated": 833832, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 280283}}} +{"time": "2026-09-28T18:29:08.825709", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7546896, "min_free_heap": 7469732, "internal": {"total": 269007, "free": 24387, "allocated": 244620, "largest_block": 8692}, "psram": {"total": 8359584, "free": 7526524, "allocated": 833060, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 282420}}} +{"time": "2026-09-28T18:29:10.950995", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618212, "min_free_heap": 7469732, "internal": {"total": 269199, "free": 25491, "allocated": 243708, "largest_block": 8692}, "psram": {"total": 8359936, "free": 7596740, "allocated": 763196, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 284533}}} +{"time": "2026-09-28T18:29:13.080057", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618484, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596832, "allocated": 763136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 286686}}} +{"time": "2026-09-28T18:29:15.232421", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 288821}}} +{"time": "2026-09-28T18:29:17.348332", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 290940}}} +{"time": "2026-09-28T18:29:19.475936", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 293060}}} +{"time": "2026-09-28T18:29:21.610209", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617692, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359952, "free": 7596028, "allocated": 763924, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 295219}}} +{"time": "2026-09-28T18:29:23.756710", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 297349}}} +{"time": "2026-09-28T18:29:25.879605", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 299466}}} +{"time": "2026-09-28T18:29:27.997245", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 301589}}} +{"time": "2026-09-28T18:29:30.122301", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 303712}}} +{"time": "2026-09-28T18:29:32.247807", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 305847}}} +{"time": "2026-09-28T18:29:34.396246", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 307970}}} +{"time": "2026-09-28T18:29:36.521300", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 310104}}} +{"time": "2026-09-28T18:29:38.637176", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7610408, "min_free_heap": 7469732, "internal": {"total": 269215, "free": 25603, "allocated": 243612, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596076, "allocated": 763892, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 312231}}} +{"time": "2026-09-28T18:29:40.785050", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 314391}}} +{"time": "2026-09-28T18:29:42.917829", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 316510}}} +{"time": "2026-09-28T18:29:45.061974", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 318643}}} +{"time": "2026-09-28T18:29:47.197222", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7618480, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359968, "free": 7596816, "allocated": 763152, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 320797}}} +{"time": "2026-09-28T18:29:49.330970", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7617084, "min_free_heap": 7469732, "internal": {"total": 269199, "free": 25407, "allocated": 243792, "largest_block": 8692}, "psram": {"total": 8359840, "free": 7595696, "allocated": 764144, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 323010}}} +{"time": "2026-09-28T18:29:51.549962", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4044, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545960, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24251, "allocated": 244740, "largest_block": 8692}, "psram": {"total": 8359504, "free": 7525712, "allocated": 833792, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 325140}}} +{"time": "2026-09-28T18:29:53.672335", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7543768, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8358944, "free": 7522012, "allocated": 836932, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 328348}}} +{"time": "2026-09-28T18:29:56.904442", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3996, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7541892, "min_free_heap": 7469732, "internal": {"total": 268975, "free": 24123, "allocated": 244852, "largest_block": 8692}, "psram": {"total": 8359360, "free": 7521772, "allocated": 837588, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 330570}}} +{"time": "2026-09-28T18:29:59.127680", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4044, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7545088, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8359440, "free": 7524836, "allocated": 834604, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 332742}}} +{"time": "2026-09-28T18:30:01.275389", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7615936, "min_free_heap": 7469732, "internal": {"total": 269167, "free": 25227, "allocated": 243940, "largest_block": 8692}, "psram": {"total": 8359744, "free": 7594724, "allocated": 765020, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 334963}}} +{"time": "2026-09-28T18:30:03.510415", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4060, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544584, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8359408, "free": 7524344, "allocated": 835064, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 337104}}} +{"time": "2026-09-28T18:30:05.635908", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7611736, "min_free_heap": 7469732, "internal": {"total": 269167, "free": 25223, "allocated": 243944, "largest_block": 8692}, "psram": {"total": 8359648, "free": 7590520, "allocated": 769128, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 339269}}} +{"time": "2026-09-28T18:30:07.813281", "tasks": {"code": 0, "data": {"tasks": [{"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "ready"}, {"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 760, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4044, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7543816, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24251, "allocated": 244740, "largest_block": 8692}, "psram": {"total": 8359392, "free": 7523580, "allocated": 835812, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 341417}}} +{"time": "2026-09-28T18:30:09.965742", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616016, "min_free_heap": 7469732, "internal": {"total": 269199, "free": 25407, "allocated": 243792, "largest_block": 8692}, "psram": {"total": 8359760, "free": 7594628, "allocated": 765132, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 343582}}} +{"time": "2026-09-28T18:30:12.111980", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4044, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544632, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8359408, "free": 7524392, "allocated": 835016, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 345704}}} +{"time": "2026-09-28T18:30:14.257671", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616012, "min_free_heap": 7469732, "internal": {"total": 269199, "free": 25403, "allocated": 243796, "largest_block": 8692}, "psram": {"total": 8359760, "free": 7594624, "allocated": 765136, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 347867}}} +{"time": "2026-09-28T18:30:16.409260", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4044, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544604, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24251, "allocated": 244740, "largest_block": 8692}, "psram": {"total": 8359408, "free": 7524360, "allocated": 835048, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 350001}}} +{"time": "2026-09-28T18:30:18.553899", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7615508, "min_free_heap": 7469732, "internal": {"total": 269199, "free": 25407, "allocated": 243792, "largest_block": 8692}, "psram": {"total": 8359728, "free": 7594120, "allocated": 765608, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 352230}}} +{"time": "2026-09-28T18:30:20.791418", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 4056, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544600, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8359408, "free": 7524360, "allocated": 835048, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 354390}}} +{"time": "2026-09-28T18:30:22.940956", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7544404, "min_free_heap": 7469732, "internal": {"total": 268991, "free": 24255, "allocated": 244736, "largest_block": 8692}, "psram": {"total": 8359392, "free": 7524168, "allocated": 835224, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 357420}}} +{"time": "2026-09-28T18:30:25.968573", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ssh_poll", "priority": 5, "stack_hwm": 3984, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 25}}, "memory": {"code": 0, "data": {"free_heap": 7544244, "min_free_heap": 7469732, "internal": {"total": 268975, "free": 24123, "allocated": 244852, "largest_block": 8692}, "psram": {"total": 8359344, "free": 7524136, "allocated": 835208, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 359616}}} +{"time": "2026-09-28T18:30:28.147610", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616884, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595220, "allocated": 764636, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 361736}}} +{"time": "2026-09-28T18:30:30.289721", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595228, "allocated": 764628, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 363876}}} +{"time": "2026-09-28T18:30:32.407254", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616884, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595220, "allocated": 764636, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 366003}}} +{"time": "2026-09-28T18:30:34.553667", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616884, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595220, "allocated": 764636, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 368150}}} +{"time": "2026-09-28T18:30:36.692568", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595240, "allocated": 764616, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 370290}}} +{"time": "2026-09-28T18:30:38.834701", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616896, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595232, "allocated": 764624, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 372439}}} +{"time": "2026-09-28T18:30:40.968177", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595228, "allocated": 764628, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 374575}}} +{"time": "2026-09-28T18:30:43.104731", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "ready"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616896, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595232, "allocated": 764624, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 376691}}} +{"time": "2026-09-28T18:30:45.226659", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595228, "allocated": 764628, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 378800}}} +{"time": "2026-09-28T18:30:47.342811", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595228, "allocated": 764628, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 380917}}} +{"time": "2026-09-28T18:30:49.466335", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595228, "allocated": 764628, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 383054}}} +{"time": "2026-09-28T18:30:51.607483", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616892, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595228, "allocated": 764628, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 385200}}} +{"time": "2026-09-28T18:30:53.730367", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7608800, "min_free_heap": 7469732, "internal": {"total": 269215, "free": 25603, "allocated": 243612, "largest_block": 8692}, "psram": {"total": 8357520, "free": 7587812, "allocated": 769708, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 387321}}} +{"time": "2026-09-28T18:30:55.878191", "tasks": {"code": 0, "data": {"tasks": [{"name": "httpd", "priority": 5, "stack_hwm": 4200, "core": 0, "state": "running"}, {"name": "IDLE1", "priority": 0, "stack_hwm": 728, "core": 1, "state": "ready"}, {"name": "IDLE0", "priority": 0, "stack_hwm": 864, "core": 0, "state": "ready"}, {"name": "ts_auto", "priority": 5, "stack_hwm": 1828, "core": 1, "state": "blocked"}, {"name": "sio_agx-info", "priority": 5, "stack_hwm": 1864, "core": 2147483647, "state": "blocked"}, {"name": "action_exec", "priority": 5, "stack_hwm": 12804, "core": 2147483647, "state": "blocked"}, {"name": "tiT", "priority": 18, "stack_hwm": 1144, "core": 2147483647, "state": "blocked"}, {"name": "power_policy", "priority": 5, "stack_hwm": 760, "core": 0, "state": "blocked"}, {"name": "websocket_task", "priority": 5, "stack_hwm": 992, "core": 2147483647, "state": "blocked"}, {"name": "w5500_tsk", "priority": 15, "stack_hwm": 2468, "core": 2147483647, "state": "blocked"}, {"name": "https_coord", "priority": 5, "stack_hwm": 5292, "core": 2147483647, "state": "blocked"}, {"name": "main", "priority": 1, "stack_hwm": 188, "core": 0, "state": "blocked"}, {"name": "power_monitor", "priority": 5, "stack_hwm": 1760, "core": 0, "state": "blocked"}, {"name": "httpd", "priority": 5, "stack_hwm": 15116, "core": 2147483647, "state": "blocked"}, {"name": "ipc1", "priority": 24, "stack_hwm": 408, "core": 1, "state": "suspended"}, {"name": "ts_console", "priority": 5, "stack_hwm": 1788, "core": 2147483647, "state": "blocked"}, {"name": "ipc0", "priority": 24, "stack_hwm": 128, "core": 0, "state": "suspended"}, {"name": "dhcp_evt", "priority": 5, "stack_hwm": 696, "core": 2147483647, "state": "blocked"}, {"name": "ts_event", "priority": 5, "stack_hwm": 668, "core": 2147483647, "state": "blocked"}, {"name": "esp_timer", "priority": 22, "stack_hwm": 2416, "core": 0, "state": "suspended"}, {"name": "led_render", "priority": 5, "stack_hwm": 1164, "core": 0, "state": "blocked"}, {"name": "sys_evt", "priority": 20, "stack_hwm": 1452, "core": 0, "state": "blocked"}, {"name": "ws_telemetry", "priority": 2, "stack_hwm": 1844, "core": 1, "state": "suspended"}, {"name": "Tmr Svc", "priority": 1, "stack_hwm": 544, "core": 2147483647, "state": "blocked"}], "count": 24}}, "memory": {"code": 0, "data": {"free_heap": 7616880, "min_free_heap": 7469732, "internal": {"total": 269231, "free": 25671, "allocated": 243560, "largest_block": 8692}, "psram": {"total": 8359856, "free": 7595216, "allocated": 764640, "largest_block": 7471092}}}, "info": {"code": 0, "data": {"app": {"name": "TianShanOS", "version": "0.5.2+3a19128d.09281801", "idf_version": "v5.5.2", "compile_time": "18:02:03", "compile_date": "Sep 28 2026"}, "chip": {"model": "ESP32-S3", "cores": 2, "revision": 2, "features": ["WiFi", "BLE"]}, "flash_size": 16777216, "uptime_ms": 389473}}} diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/serial-redacted.log b/docs/repair/ssh-poll-stack/device-diagnostic/serial-redacted.log new file mode 100644 index 0000000..3068593 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/serial-redacted.log @@ -0,0 +1,748 @@ +I (99) boot: 6 storage Unknown data 01 82 00620000ESP-ROM:esp32s3-20210327 +Build:Mar 27 2021 +rst:0x15 (USB_UART_CHIP_RESET),boot:0x8 (SPI_FAST_FLASH_BOOT) +Saved PC:0x4037c498 +SPIWP:0xee +mode:DIO, clock div:1 +load:0x3fce2820,len:0x1700 +load:0x403c8700,len:0xec0 +load:0x403cb700,len:0x31c0 +entry 0x403c894c +I (24) boot: ESP-IDF v5.5.2 2nd stage bootloader +I (24) boot: compile time Sep 28 2026 18:02:10 +I (25) boot: Multicore bootloader +I (25) boot: chip revision: v0.2 +I (27) boot: efuse block revision: v1.3 +I (31) qio_mode: Enabling default flash chip QIO +I (35) boot.esp32s3: Boot SPI Speed : 80MHz +I (39) boot.esp32s3: SPI Mode : QIO +I (43) boot.esp32s3: SPI Flash Size : 16MB +I (47) boot: Enabling RNG early entropy source... +I (51) boot: Partition Table: +I (54) boot: ## Label Usage Type ST Offset Length +I (60) boot: 0 nvs WiFi data 01 02 00009000 0000c000 +I (67) boot: 1 nvs_keys NVS keys 01 04 00015000 00001000 +I (73) boot: 2 otadata OTA data 01 00 00016000 00002000 +I (80) boot: 3 phy_init RF data 01 01 00018000 00001000 +I (86) boot: 4 ota_0 OTA app 00 10 00020000 00300000 +I (93) boot: 5 ota_1 OTA app 00 11 00320000 00300000 +I (99) boot: 6 storage Unknown data 01 82 00620000 00080000 +I (106) boot: 7 www Unknown data 01 82 006a0000 00300000 +I (112) boot: 8 fatfs Unknown data 01 81 009a0000 00010000 +I (119) boot: End of partition table +I (123) esp_image: segment 0: paddr=00020020 vaddr=3c1a0020 size=9714ch (618828) map +I (222) esp_image: segment 1: paddr=000b7174 vaddr=3fca2d00 size=04f1ch ( 20252) load +I (226) esp_image: segment 2: paddr=000bc098 vaddr=40374000 size=03f80h ( 16256) load +I (229) esp_image: segment 3: paddr=000c0020 vaddr=42000020 size=19f160h (1700192) map +I (485) esp_image: segment 4: paddr=0025f188 vaddr=40377f80 size=1ad00h (109824) load +I (507) esp_image: segment 5: paddr=00279e90 vaddr=50000000 size=00020h ( 32) load +I (519) boot: Loaded app from partition at offset 0x20000 +I (519) boot: Disabling RNG early entropy source... +I (529) octal_psram: vendor id : 0x0d (AP) +I (529) octal_psram: dev id : 0x02 (generation 3) +I (530) octal_psram: density : 0x03 (64 Mbit) +I (532) octal_psram: good-die : 0x01 (Pass) +I (536) octal_psram: Latency : 0x01 (Fixed) +I (540) octal_psram: VCC : 0x01 (3V) +I (544) octal_psram: SRF : 0x01 (Fast Refresh) +I (549) octal_psram: BurstType : 0x01 (Hybrid Wrap) +I (554) octal_psram: BurstLen : 0x01 (32 Byte) +I (559) octal_psram: Readlatency : 0x02 (10 cycles@Fixed) +I (564) octal_psram: DriveStrength: 0x00 (1/1) +I (568) MSPI Timing: Enter psram timing tuning +I (573) esp_psram: Found 8MB PSRAM device +I (576) esp_psram: Speed: 80MHz +I (579) cpu_start: Multicore app +I (1018) esp_psram: SPI SRAM memory test OK +I (1026) cpu_start: GPIO 44 and 43 are used as console UART I/O pins +I (1027) cpu_start: Pro cpu start user code +I (1027) cpu_start: cpu freq: 240000000 Hz +I (1029) app_init: Application information: +I (1033) app_init: Project name: TianShanOS +I (1037) app_init: App version: 0.5.2+3a19128d.09281801 +I (1043) app_init: Compile time: Sep 28 2026 18:02:03 +I (1048) app_init: ELF file SHA256: e6fa1eadb... +I (1052) app_init: ESP-IDF: v5.5.2 +I (1056) efuse_init: Min chip rev: v0.0 +I (1060) efuse_init: Max chip rev: v0.99 +I (1064) efuse_init: Chip rev: v0.2 +I (1068) heap_init: Initializing. RAM available for dynamic allocation: +I (1074) heap_init: At 3FCB6E78 len 00032898 (202 KiB): RAM +I (1080) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM +I (1085) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM +I (1090) heap_init: At 600FE000 len 00001FE8 (7 KiB): RTCRAM +I (1096) esp_psram: Adding pool of 8179K of PSRAM memory to heap allocator +I (1103) spi_flash: detected chip: generic +I (1106) spi_flash: flash io: qio +I (1110) sleep_gpio: Configure to isolate all GPIO pins in sleep state +I (1115) sleep_gpio: Enable automatic switching of GPIO sleep configuration +I (1122) main_task: Started on CPU0 +I (1125) esp_psram: Reserving pool of 16K of internal memory for DMA/internal allocations +I (1133) main_task: Calling app_main() + +╔════════════════════════════════════════════════════════════════════════╗ +║ ║ +║ ████████╗██╗ █████╗ ███╗ ██╗███████╗██╗ ██╗ █████╗ ███╗ ██╗ ║ +║ ╚══██╔══╝██║██╔══██╗████╗ ██║██╔════╝██║ ██║██╔══██╗████╗ ██║ ║ +║ ██║ ██║███████║██╔██╗ ██║███████╗███████║███████║██╔██╗ ██║ ║ +║ ██║ ██║██╔══██║██║╚██╗██║╚════██║██╔══██║██╔══██║██║╚██╗██║ ║ +║ ██║ ██║██║ ██║██║ ╚████║███████║██║ ██║██║ ██║██║ ╚████║ ║ +║ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ║ +║ ║ +║ TianShanOS 0.5.2+3a19128d.09281801 ║ +║ ESP32 Rack Management Operating System ║ +║ ║ +╚════════════════════════════════════════════════════════════════════════╝ + +I (1308) main: System Information: +I (1311) main: - IDF Version: v5.5.2 +I (1314) main: - Free Heap: 8598788 bytes +I (1318) main: - Min Free Heap: 8598788 bytes +I (1322) main: - Chip: ESP32-S3, 2 cores, WiFi/BLE +I (1327) main: Initializing TianShanOS... +I (1331) ts_core: TianShanOS Core v0.5.2+3a19128d.09281801 initializing... +I (1338) ts_mempool: Initializing memory pools in PSRAM... +I (1343) ts_mempool: Pool 0: 16 x 256 bytes = 4 KB (PSRAM) +I (1348) ts_mempool: Pool 1: 12 x 1024 bytes = 12 KB (PSRAM) +I (1353) ts_mempool: Pool 2: 8 x 4096 bytes = 32 KB (PSRAM) +I (1359) ts_mempool: Pool 3: 4 x 8192 bytes = 32 KB (PSRAM) +I (1364) ts_mempool: Memory pools initialized successfully +I (1369) ts_core: Memory pools initialized in PSRAM +I (1374) ts_core: cJSON PSRAM hooks installed +I (1378) ts_core: Initializing configuration system... +I (1383) ts_config: Initializing TianShanOS Configuration System... +I (1389) ts_config: Configuration system initialized successfully +I (1394) ts_config_nvs: Initializing NVS configuration backend... +I (1461) ts_config_nvs: NVS backend initialized (namespace: ts_config) +I (1461) ts_config: Registered backend 1 with priority 80 +I (1461) ts_config_file: Initializing file configuration backend... +I (1467) ts_config_file: File backend initialized (waiting for storage) +I (1474) ts_config: Registered backend 2 with priority 60 +I (1479) ts_core: Initializing logging system... +I (1483) ts_log: Initializing TianShanOS Logging System... +I (1493) ts_log: Log buffer allocated in PSRAM (500 entries, 148000 bytes) +I (1497) ts_log: ESP_LOG capture hook installed +I (1502) ts_log: Logging system initialized (level=3, outputs=0x05, buffer=500) +I (1510) ts_core: Initializing event system... +I (1514) ts_event: Initializing TianShanOS Event System... +I (1519) ts_event: Event loop task started +I (1523) ts_event: Event system initialized (queue_size=32) +I (1529) ts_config_file: Registered storage event handler for auto-load +I (1535) ts_config_schemas: Initializing configuration module system... +I (1541) ts_config_module: Initializing configuration module system... +I (1548) ts_config_meta: Initializing configuration meta management... +I (1556) ts_config_meta: Meta initialized: global_seq=6, sync_seq=6, pending=0x00 +I (1561) ts_config_module: Configuration module system initialized +I (1567) ts_config_schemas: Registering configuration modules... +I (1573) ts_config_module: Registered module NET (nvs=ts_net, schema_v=1) +I (1579) ts_config_module: Registered module DHCP (nvs=ts_dhcp, schema_v=1) +I (1586) ts_config_module: Registered module WIFI (nvs=ts_wifi, schema_v=1) +I (1593) ts_config_module: Registered module NAT (nvs=ts_nat, schema_v=1) +I (1599) ts_config_module: Registered module LED (nvs=ts_led, schema_v=1) +I (1606) ts_config_module: Registered module FAN (nvs=ts_fan, schema_v=1) +I (1612) ts_config_module: Registered module DEVICE (nvs=ts_device, schema_v=1) +I (1619) ts_config_module: Registered module SYSTEM (nvs=ts_system, schema_v=1) +I (1626) ts_config_module: Registered module TEMP (nvs=ts_temp, schema_v=0) +I (1633) ts_config_module: Registered module RULES (nvs=ts_rules, schema_v=0) +I (1640) ts_config_module: Registered module ACTIONS (nvs=ts_actions, schema_v=0) +I (1647) ts_config_module: Registered module SOURCES (nvs=ts_sources, schema_v=0) +I (1654) ts_config_schemas: All configuration modules registered +I (1660) ts_config_schemas: Loading module configurations... +I (1665) ts_config_module: Loading module NET... +I (1670) ts_config_module: Using schema defaults for module NET +I (1676) ts_config_module: Loading module DHCP... +I (1680) ts_config_module: Using schema defaults for module DHCP +I (1686) ts_config_module: Loading module WIFI... +I (1690) ts_config_module: Using schema defaults for module WIFI +I (1696) ts_config_module: Loading module NAT... +I (1700) ts_config_module: Using schema defaults for module NAT +I (1706) ts_config_module: Loading module LED... +I (1710) ts_config_module: Using schema defaults for module LED +I (1716) ts_config_module: Loading module FAN... +I (1722) ts_config_module: Loading module DEVICE... +I (1724) ts_config_module: Using schema defaults for module DEVICE +I (1731) ts_config_module: Loading module SYSTEM... +I (1735) ts_config_module: Using schema defaults for module SYSTEM +I (1741) ts_config_module: Loading module TEMP... +I (1745) ts_config_module: Loading module RULES... +I (1750) ts_config_module: Using schema defaults for module RULES +I (1756) ts_config_module: Loading module ACTIONS... +I (1760) ts_config_module: Using schema defaults for module ACTIONS +I (1766) ts_config_module: Loading module SOURCES... +I (1771) ts_config_module: Using schema defaults for module SOURCES +I (1777) ts_config_meta: === Configuration Meta === +I (1781) ts_config_meta: global_seq: 6 +I (1785) ts_config_meta: sync_seq: 6 +I (1789) ts_config_meta: pending_sync: 0x00 +I (1793) ts_config_meta: Schema versions: +I (1797) ts_config_meta: ========================== +I (1802) ts_config_schemas: Configuration module system initialized +I (1808) ts_core: Initializing service management... +I (1812) ts_service: Initializing TianShanOS Service Management... +I (1818) ts_service: Service management initialized +I (1823) ts_core: TianShanOS Core initialized successfully +I (1828) main: Registering core services... +I (1832) ts_services: Registering services... +I (1836) ts_service: Registered service: hal (phase=HAL) +I (1841) ts_services: - hal service registered +I (1845) ts_service: Registered service: storage (phase=DRIVER) +I (1851) ts_services: - storage service registered +I (1856) ts_service: Registered service: led (phase=DRIVER) +I (1861) ts_services: - led service registered +I (1865) ts_service: Registered service: drivers (phase=DRIVER) +I (1871) ts_services: - drivers service registered +I (1876) ts_service: Registered service: power (phase=DRIVER) +I (1881) ts_services: - power service registered +I (1886) ts_service: Registered service: network (phase=NETWORK) +I (1891) ts_services: - network service registered +I (1896) ts_service: Registered service: security (phase=SECURITY) +I (1902) ts_services: - security service registered +I (1907) ts_service: Registered service: api (phase=SERVICE) +I (1912) ts_services: - api service registered +I (1916) ts_service: Registered service: https (phase=SERVICE) +I (1922) ts_services: - https service registered +I (1926) ts_service: Registered service: webui (phase=UI) +I (1932) ts_services: - webui service registered +I (1936) ts_service: Registered service: console (phase=UI) +I (1941) ts_services: - console service registered +I (1946) ts_service: Registered service: automation (phase=SERVICE) +I (1952) ts_services: - automation service registered +I (1957) ts_services: All core services registered +I (1962) main: Starting TianShanOS services... +I (1966) ts_core: Starting TianShanOS... +I (1969) ts_service: Starting all services... +I (1973) ts_service: === Phase 0: PLATFORM === +I (1978) ts_service: === Phase 1: CORE === +I (1981) ts_service: === Phase 2: HAL === +I (1985) ts_service: Starting 1 services in phase HAL +I (1990) ts_service: Starting service: hal +I (1994) ts_services: Initializing HAL service... +I (903) ts_hal: Initializing HAL module v1.0.0 +I (908) ts_pin: Initializing pin manager +I (912) ts_pin: Pin manager initialized +I (917) ts_hal: No pin config in NVS, loading defaults +I (923) ts_pin: Loading default pin mappings for ESP32S3 +I (929) ts_gpio: Initializing GPIO subsystem +I (934) ts_hal: Early hardware init: setting reset pins to safe state +I (941) ts_hal: W5500_RST (GPIO39) = HIGH (normal) +I (946) ts_hal: AGX_RESET (GPIO1) = LOW (normal) +I (952) ts_hal: AGX_POWER (GPIO3) = LOW (allow boot) +I (957) ts_pwm: Initializing PWM subsystem +I (962) ts_i2c: Initializing I2C subsystem +I (967) ts_spi: Initializing SPI subsystem +I (971) ts_uart: Initializing UART subsystem +I (976) ts_adc: Initializing ADC subsystem +I (981) ts_hal: HAL initialization complete, platform: ESP32S3 +I (2083) ts_service: Service 'hal' started in 90 ms +I (2088) ts_service: === Phase 3: DRIVER === +I (2092) ts_service: Starting 4 services in phase DRIVER +I (2097) ts_service: Starting service: power +I (2101) ts_services: Initializing power service... +I (1010) ts_power_policy: Initializing power policy v1.0.0 +I (1016) ts_power_policy: NVS: enabled_on_boot = true +I (1022) ts_power_policy: Registered SD card mount event handler +I (1029) ts_power_policy: Power policy initialized (Low: 12.6V, Recovery: 18.0V, Delay: 60s) [source: defaults] +I (2135) ts_power_monitor: Initializing power monitor v1.0.0 +I (2140) ts_power_monitor: Initializing voltage monitor on GPIO 18 (ADC2_CH7) +I (2148) ts_power_monitor: ADC calibration initialized +I (2152) ts_power_monitor: Voltage monitor initialized (divider ratio: 11.4:1) +I (2159) ts_power_monitor: Initializing power chip communication on GPIO 47 (UART1) +I (2167) uart: queue free spaces: 10 +I (2170) ts_power_monitor: Power chip communication initialized (baud: 9600) +I (2177) ts_power_monitor: Power monitor initialized successfully +I (2182) ts_services: Starting power service... +I (2186) ts_power_monitor: Starting power monitor +I (2191) ts_power_monitor: Power monitor task started +I (2196) ts_power_monitor: Power monitor started +I (1104) ts_power_policy: Starting power policy monitoring +I (1111) ts_power_policy: Power policy task started +I (1116) ts_power_policy: Power policy monitoring started +I (2218) ts_services: Power protection started (auto-start enabled) +I (2224) ts_service: Service 'power' started in 123 ms +I (2229) ts_service: Starting service: drivers +I (2233) ts_services: Initializing drivers service... +I (1142) ts_drivers: Initializing device drivers +I (1148) ts_temp_source: Loaded preferred source from NVS: variable +I (1156) ts_temp_source: Loaded 1 weighted bound vars from NVS +I (1161) ts_temp_source: Temperature source manager initialized (v1.0.0), preferred: variable +I (1170) ts_drivers: Temperature source manager initialized +I (1176) ts_fan: Subscribed to temperature events +I (1182) ts_fan: Fan driver initialized +I (1187) ts_fan: Fan 0 configured: PWM=GPIO41, TACH=-1, curve=0 points +I (1193) ts_drivers: Fan 0 configured on GPIO 41 +I (1199) ts_power: Power monitor initialized +I (1203) ts_device: Device control initialized +I (1209) ts_device: AGX configured: FORCE_SHUTDOWN=GPIO3(LOW=run), RESET=GPIO1(LOW=normal) +I (1218) ts_drivers: AGX configured (pwr=3, rst=1, rcv=40) +I (1224) ts_device: LPMU configured (power=46[pulse HIGH], reset=2[pulse HIGH]) +I (1232) ts_drivers: LPMU configured (pwr=46, rst=2) +I (1237) ts_usb_mux: USB MUX driver initialized +I (1243) ts_usb_mux: Loaded USB MUX target from NVS: 0 +I (1249) ts_usb_mux: USB MUX -> ESP32 (sel0=0, sel1=0) +I (1254) ts_usb_mux: USB MUX configured (sel0=8, sel1=48), restored target: 0 +I (1262) ts_drivers: USB MUX configured (sel0=8, sel1=48) +I (2364) ts_compute_monitor: Initializing compute monitor v1.0.0 +I (1274) ts_temp_source: Provider registered: agx_cpu (agx) +I (2376) ts_compute_monitor: Initialized, server: 10.10.99.98:58090 +I (1286) ts_drivers: Compute monitor initialized (use 'compute --start' to connect) +I (1294) ts_drivers: Device drivers initialized +I (1300) ts_fan: Restored fan 0: mode=2, duty=25%, curve=9 pts +I (2402) ts_service: Service 'drivers' started in 169 ms +I (2407) ts_service: Starting service: led +I (2411) ts_services: Initializing LED service... +I (1320) led_cc: Loaded config from NVS +I (1325) led_cc: Color correction initialized (enabled=true) +I (1330) ts_led: LED subsystem initialized +I (2430) ts_services: Starting LED service... +I (1339) led_preset: Touch LED: using hardcoded GPIO 45 +I (1345) led_driver: Using RMT backend for 1 LEDs on GPIO 45 +I (1353) led_driver: LED driver initialized: 'led_touch' - GPIO 45, 1 LEDs +I (1359) ts_led: Created LED device 'led_touch' with 1 LEDs +I (1365) led_preset: Touch LED initialized: 1 LEDs on GPIO 45 +I (1372) led_preset: Board LED: using hardcoded GPIO 42 +I (1378) led_driver: Using RMT backend for 28 LEDs on GPIO 42 +I (1386) led_driver: LED driver initialized: 'led_board' - GPIO 42, 28 LEDs +I (1392) ts_led: Created LED device 'led_board' with 28 LEDs +I (1398) led_preset: Board LED initialized: 28 LEDs on GPIO 42 +I (1404) led_preset: Matrix LED: pin_manager returned GPIO 9 +I (1411) led_driver: Using SPI backend for 1024 LEDs on GPIO 9 +I (1449) led_driver: LED driver initialized: 'led_matrix' - GPIO 9, 1024 LEDs +I (1450) ts_led: Created LED device 'led_matrix' with 1024 LEDs +I (1453) led_preset: Matrix LED initialized: 32x32 on GPIO 9 +I (1459) led_preset: Loading LED boot configurations... +I (1473) led_preset: Restored touch: animation=solid, speed=50, brightness=80, color=#FFCCCC +I (1476) led_preset: Restored board: animation=solid, speed=50, brightness=60, color=#FFFFFF +I (1485) led_preset: Restored matrix: animation=solid, speed=50, brightness=52, color=#FFFFFF +I (2588) ts_service: Service 'led' started in 178 ms +I (2593) ts_service: Starting service: storage +I (2597) ts_services: Initializing storage service... +I (1511) ts_storage: Storage subsystem initialized +I (2607) ts_services: Starting storage service... +I (1516) storage_spiffs: Mounting SPIFFS at /spiffs (partition: storage) +I (1569) storage_spiffs: SPIFFS mounted: 474641 total, 0 used, 474641 free +I (2665) ts_services: SPIFFS mounted at /spiffs +I (1570) storage_sd: Good: /sdcard not in FATFS s_fat_ctxs[] (info returned ESP_ERR_INVALID_STATE) +I (1580) storage_sd: Mounting SD card at /sdcard (mode: 2, freq: 20000 kHz) +I (1591) storage_sd: SD GPIO: CMD=15, CLK=16, D0=4, D1=5, D2=6, D3=7 +I (2741) ts_config: Saving configuration... +I (2749) ts_config: Saved configuration to backend 1 +I (2750) ts_config: Configuration saved +I (1656) storage_sd: SD card mounted: +I (1656) storage_sd: Name: MSSD0 +I (1659) storage_sd: Type: SDHC/SDXC +I (1671) storage_sd: Speed: default +I (1671) storage_sd: Size: 29850MB +I (1672) ts_power_policy: SD card mounted, syncing power policy config... +I (2776) ts_services: SD card mounted at /sdcard +I (2780) ts_config_pack: Loaded plain config: /sdcard/config/power_policy.json (180 bytes) +I (1693) ts_power_policy: SD: low_voltage_threshold = 12.60V +I (1699) ts_power_policy: SD: recovery_voltage_threshold = 18.00V +I (1706) ts_power_policy: SD: shutdown_delay_sec = 60 +I (1711) ts_power_policy: SD: recovery_hold_sec = 5 +I (2811) ts_recovery: Checking for SD card recovery... +I (1717) ts_power_policy: SD: fan_stop_delay_sec = 60 +I (1727) ts_power_policy: SD: enabled_on_boot = true +I (1733) ts_power_policy: Loaded power policy config from SD card +I (1740) ts_power_policy: Config loaded from SD card, syncing to NVS +I (2843) ts_config: Saving configuration... +I (2854) ts_config: Saved configuration to backend 1 +I (2854) ts_config: Configuration saved +I (2855) ts_config_file: SD card mounted, loading configuration files... +I (2860) ts_recovery: No recovery directory found +I (2862) ts_config_file: Loading configuration files from: /sdcard/config +I (2875) ts_service: Service 'storage' started in 276 ms +I (2876) ts_config_file: Loading: power_policy.json +I (2881) ts_config_json: Loading JSON config: /sdcard/config/power_policy.json +I (2890) ts_service: === Phase 4: NETWORK === +I (2893) ts_config_json: JSON config loaded successfully +I (2898) ts_config_file: Loading: led_color_correction.json +I (2902) ts_service: Starting 1 services in phase NETWORK +I (2903) ts_config_json: Loading JSON config: /sdcard/config/led_color_correction.json +I (2917) ts_service: Starting service: network +I (2920) ts_config_json: JSON config loaded successfully +I (2925) ts_config_file: Loading: fan_curve_config_0.json +I (2930) ts_config_json: Loading JSON config: /sdcard/config/fan_curve_config_0.json +I (2943) ts_config_json: JSON config loaded successfully +I (2944) ts_config_file: Loading: fan.json +I (2946) ts_config_json: Loading JSON config: /sdcard/config/fan.json +I (2948) ts_services: Initializing network service... +I (2956) ts_config_json: JSON config loaded successfully +I (2964) ts_config_file: Loading: ui_widgets.json +I (2967) ts_config_json: Loading JSON config: /sdcard/config/ui_widgets.json +I (1878) ts_net_mgr: Initializing network manager... +I (2978) ts_config_json: JSON config loaded successfully +I (2985) ts_config_file: Loaded 5 JSON configs, skipped 1 +I (2989) ts_config_file: Configuration files loaded successfully +I (1884) ts_net_mgr: No saved config in NVS, using defaults +I (1907) ts_net_mgr: Ethernet pins: MOSI=11 MISO=13 SCLK=12 CS=10 INT=38 RST=39 +I (1914) ts_eth: Initializing Ethernet (W5500) +I (1919) ts_eth: Created Ethernet netif with DHCP server mode +I (1925) ts_eth: Device IP: 10.10.99.97 +I (1936) ts_eth: Gateway: 10.10.99.100 +I (1936) ts_eth: Netmask: 255.255.255.0 +I (1961) ts_eth: Ethernet MAC: 20:6e:f1:a1:d5:8f +I (3058) esp_eth.netif.netif_glue: 20:6e:f1:a1:d5:8f +I (3058) esp_eth.netif.netif_glue: ethernet attached to netif +I (1967) ts_eth: DHCP lease range configured: 10.10.99.100 - 10.10.99.103 +I (1976) ts_eth: DHCP DNS server configured: 8.8.8.8 +I (1979) ts_eth: Ethernet initialized +I (1984) ts_net_mgr: Ethernet initialized, MAC: 20:6e:f1:a1:d5:8f +I (1990) ts_net_mgr: Network manager initialized +I (1996) ts_dhcps: Initializing DHCP server... +I (2001) ts_dhcps: DHCP event task started +I (2006) ts_dhcps: No saved config, using defaults +I (2017) ts_dhcps: DHCP server initialized (event queue enabled) +I (3113) ts_services: Starting network service... +I (2022) ts_net_mgr: Starting Ethernet... +I (2027) ts_net_mgr: Using static IP: 10.10.99.97 +I (2042) ts_net_mgr: Ethernet started +I (2043) ts_eth: Ethernet started +I (2043) ts_net_mgr: Ethernet started, waiting for link... +I (3143) ts_time_sync: Timezone set to: CST-8 +I (3152) ts_time_sync: Time sync module initialized +I (3152) ts_time_sync: NTP server 1: 10.10.99.99 +I (3155) ts_time_sync: NTP server 2: 10.10.99.98 +I (3160) ts_time_sync: NTP server 3: 10.10.99.100 +I (3165) ts_time_sync: Starting NTP sync with primary: 10.10.99.99, secondary: 10.10.99.98 +I (3173) ts_time_sync: NTP synchronization started (retry enabled for unreliable servers) +I (2085) ts_device: LPMU startup detection: waiting for network... +I (2099) ts_device: LPMU startup detection task started +I (3195) ts_service: Service 'network' started in 247 ms +I (3198) ts_service: === Phase 5: SECURITY === +I (3202) ts_service: Starting 1 services in phase SECURITY +I (3208) ts_service: Starting service: security +I (3212) ts_services: Initializing security service... +I (3219) ts_ssh_hosts_cfg: NVS has 0 hosts, will load from SD card in background +I (3225) ts_ssh_hosts_cfg: SSH hosts config initialized (SD card loading deferred) +I (3277) ts_ssh_cmd_cfg: NVS has 6 commands, will load from SD card in background +I (3277) ts_ssh_cmd_cfg: SSH commands config initialized (SD card loading deferred) +I (2186) ts_security: Security subsystem initialized +I (3286) ts_keystore: Initializing secure keystore... +I (3291) ts_keystore: Keystore initialized +I (3295) ts_known_hosts: Known hosts module initialized +I (3501) ts_cert: Initialized, status: activated, has_key=1, has_cert=1 +I (3502) pki_client: PKI client initialized, server=10.10.99.100:57443, device_id=TIANSHAN-DEVICE-001 +I (3506) ts_services: Certificate status: activated, time validity: valid +I (3516) ts_config_pack: Config pack system initialized, device fingerprint: 50c2e523d3483956... +I (3521) ts_config_file: Loading encrypted configuration files from: /sdcard/config +I (3532) ts_service: Service 'security' started in 320 ms +I (3533) ts_service: === Phase 6: SERVICE === +I (3537) ts_service: Starting 3 services in phase SERVICE +I (3542) ts_service: Starting service: automation +I (3555) ts_services: Initializing automation service... +I (3556) ts_automation: Initializing automation engine v1.0.0 +I (3562) ts_source_mgr: Initializing source manager (max 16) +I (3563) ts_source_mgr: Source manager initialized (loading deferred) +I (3569) ts_rule_engine: Initializing rule engine (max 32 rules) +I (3575) ts_rule_engine: Rule engine initialized (loading deferred) +I (3580) ts_action_mgr: Initializing action manager +I (3595) ts_action_mgr: Action executor task started (DRAM stack) +I (3596) ts_action_mgr: Action manager initialized (loading deferred) +I (3597) ts_automation: Loading config from: /sdcard/config/automation.json +I (3606) ts_ssh_cmd_cfg: Pre-creating variables for all SSH commands +I (2558) ts_power_policy: Registered 8 automation variables for power policy +I (3654) ts_automation: Automation engine initialized +I (3655) ts_services: Starting automation service... +I (3660) ts_source_mgr: Starting all data sources +I (3977) ts_config: Saving configuration... +I (3991) ts_config: Saved configuration to backend 1 +I (3991) ts_config: Configuration saved +I (4044) ts_net_mgr: Ethernet link up +I (4044) ts_net_mgr: Ethernet IP (static/DHCPS): 10.10.99.97 +I (4045) ts_net: mDNS disabled by config +I (4048) ts_eth: Ethernet link up +I (4052) ts_eth: Ethernet MAC: 20:6e:f1:a1:d5:8f +I (5172) ts_source_mgr: Network ready, starting external sources +I (5172) ts_automation: Automation task started +I (5172) ts_services: Automation engine running: 0 sources, 0 rules, 36 variables +I (5178) ts_service: Service 'automation' started in 1622 ms +I (5183) ts_service: Starting service: https +I (5188) ts_https: HTTPS server deinitialized +I (5192) ts_https: HTTPS server initialized (port=443, mTLS=required) +I (5198) ts_https_api: Registering permission test endpoints... +I (5203) ts_https: Registered endpoint: GET / (min_role=anonymous) +I (5209) ts_service: Service 'https' started in 21 ms +I (5209) ts_https: Registered endpoint: GET /api/auth/whoami (min_role=viewer) +I (5221) ts_https: Registered endpoint: GET /api/test/viewer (min_role=viewer) +I (5228) ts_https: Registered endpoint: GET /api/test/operator (min_role=operator) +I (5235) ts_https: Registered endpoint: GET /api/test/admin (min_role=admin) +I (5242) ts_https: Registered endpoint: POST /api/test/admin-action (min_role=admin) +I (5250) ts_https: mTLS enabled: client certificates required +I (4153) ts_dhcps: Starting DHCP server on ethernet... +I (5255) esp_https_server: Starting server +I (4165) ts_dhcps: Ethernet IP preserved: 10.10.99.97 +I (5266) esp_https_server: Server listening on port 443 +I (4175) ts_dhcps: Applied config for ethernet: +I (5276) ts_https: HTTPS server started on port 443 with 6 endpoints +I (4187) ts_dhcps: Gateway: 10.10.99.100 +I (4197) ts_dhcps: Pool: 10.10.99.100 - 10.10.99.103 +I (4204) ts_dhcps: Lease: 1440 min +I (4211) ts_dhcps: DHCP server started on ethernet +I (4212) ts_eth: DHCP server started via ts_dhcp_server +I (5313) ts_ssh_cmd_cfg: Deferred: checking SD card for config (NVS has 6 commands)... +I (5254) ts_service: Starting service: api +I (5323) ts_ssh_cmd_cfg: SD card has config, clearing NVS and importing... +I (5332) ts_services: Initializing API service... +I (5347) ts_ssh_cmd_cfg: Cleared all SSH commands +I (4253) ts_api: API endpoints allocated in PSRAM (25344 bytes) +I (5353) ts_ssh_cmd_cfg: Cleared all SSH commands +I (4263) ts_api: API layer initialized (max 288 endpoints) +I (5366) ts_services: Starting API service... +I (5370) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3_6-35B-A3B.json (1095 bytes) +I (4305) ts_api: Registering all API modules... +I (4307) api_config: Config API registered (11 endpoints) +I (4308) api_device: Registering device APIs +I (4311) api_led: Registering LED APIs +I (5414) ts_ssh_cmd_cfg: Added SSH command: Qwen3.6-35B-A3B (Qwen3_6-35B-A3B) +I (4319) api_network: Registering network APIs +I (5428) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3-Embedding-0_6B.json (885 bytes) +I (4335) api_fan: Registering fan APIs +I (4351) api_power: Registering power APIs +I (4356) api_temp: Registering temperature APIs +I (4357) api_service: Registering service APIs... +I (4360) api_service: Service APIs registered (5 endpoints) +I (4365) api_storage: Registering storage APIs... +I (4372) api_storage: Storage APIs registered (9 endpoints) +I (4377) api_gpio: Registering GPIO APIs... +I (4401) api_gpio: I (5498) ts_ssh_cmd_cfg: Added SSH command: Qwen3-Embedding-0.6B (Qwen3-Embedding-0_6B) +GPIO APIs registered (4 endpoints) +I (4413) api_monitor: Registering monitor APIs... +I (5518) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3-Reranker-0_6B.json (1064 bytes) +I (4442) api_monitor: Monitor APIs registered: 6 endpoints +I (4462) api_ssh: Registering SSH APIs... +I (4464) api_sftp: Registering SFTP APIs... +I (5562) ts_api_ota: Registering OTA APIs +I (5565) ts_ota: Running from partition: ota_0 (addr=0x20000, size=3072 KB) +I (5569) ts_ota: OTA subsystem initialized +I (5602) ts_api_ota: Loaded OTA server URL: (not set) +I (5605) ts_ssh_cmd_cfg: Added SSH command: Qwen3-Reranker-0.6B (Qwen3-Reranker-0_6B) +I (5616) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/drop.json (395 bytes) +I (5672) ts_api_ota: Registered 21 OTA API endpoints +I (5686) ts_ssh_cmd_cfg: Added SSH command: drop (drop) +I (4593) api_log: Log API endpoints registered +I (4596) api_automation: Registering automation APIsI (5699) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/Qwen3_8_27B_Quark_INT4_MTP3.json (672 bytes) + +I (4627) api_automation: Automation APIs registered +I (4629) api_cert: Certificate APIs registered +I (5728) ts_ssh_hosts_cfg: Deferred: checking SD card for config (NVS has 0 hosts)... +I (5734) ts_ssh_hosts_cfg: SD card has config, clearing NVS and importing... +I (5820) ts_ssh_cmd_cfg: Added SSH command: Qwen3.8-27B-Quark-INT4-MTP3 (Qwen3_8_27B_Quark_INT4_MTP3) +I (5833) ts_ssh_hosts_cfg: Cleared all SSH host configs +I (5846) ts_ssh_hosts_cfg: Cleared all SSH host configs +I (5848) ts_ssh_cmd_cfg: Async sync to SD card... +I (4754) ts_auth: Auth module initialized (version 3) +I (5851) ts_config_pack: Loading encrypted config: /sdcard/config/ssh_hosts/rm01@10.10.99.98.tscfg +I (5860) ts_ssh_cmd_cfg: Async sync to SD card... +I (5860) ts_config_pack: Loaded plain config: /sdcard/config/ssh_commands/quark_stop_repair.json (472 bytes) +I (4784) api_auth: Auth APIs registered +I (4786) api_ui: Registering UI APIs +I (4799) api_config_pack: Config Pack API registered (8 endpoints) +I (4802) ts_api: All API modules registered (263 endpoints) +I (5900) ts_service: Service 'api' started in 567 ms +I (5922) ts_service: === Phase 7: UI === +I (5929) ts_service: Starting 2 services in phase UI +I (5937) ts_service: Starting service: console +I (5940) ts_services: Initializing console service... +I (5990) ts_ssh_cmd_cfg: Exported 5 SSH commands to /sdcard/config/ssh_commands/ +I (6116) ts_ssh_cmd_cfg: Added SSH command: Quark进程与内存检查 (quark_stop_repair) +I (6122) ts_ssh_cmd_cfg: Loaded 6 SSH commands from directory: /sdcard/config/ssh_commands (skipped 0) +I (6124) ts_source_mgr: Deferred source loading started +I (4852) ts_i18n: I18n initialized, language: English +I (5069) ts_console: Console initialized +I (5113) cmd_register: Registering all console commands... +I (5137) cmd_system: System commands registered +I (5166) cmd_service: Service commands registered +I (6289) ts_ssh_cmd_cfg: Exported 6 SSH commands to /sdcard/config/ssh_commands/ +I (6328) ts_ssh_cmd_cfg: Loaded 6 commands from SD card (.tscfg > .json) +I (6336) ts_ssh_hosts_cfg: Async sync to SD card... +I (6344) ts_ssh_hosts_cfg: Exported 0 SSH hosts to /sdcard/config/ssh_hosts/ +I (6347) ts_ssh_hosts_cfg: Async sync to SD card... +I (6356) ts_ssh_hosts_cfg: Exported 0 SSH hosts to /sdcard/config/ssh_hosts/ +I (5268) cmd_config: Config commands registered (with pack support) +I (5288) cmd_fan: Fan commands registered (API mode) +I (5292) cmd_storage: Storage commands registered +I (5296) cmd_net: Network commands registered +I (5299) cmd_device: Device commands registered +I (5304) cmd_led: LED commands registered +I (5308) cmd_wifi: WiFi commands registered +I (5309) ts_nat: Initializing NAT module +I (5330) ts_nat: No saved NAT config, using defaults +I (5331) ts_nat: NAT module initialized (auto_start=yes) +I (6408) ts_config_pack: Loaded plain config: /sdcard/config/sources/agx-info.json (192 bytes) +I (6442) ts_source_mgr: Loaded 1 sources from directory: /sdcard/config/sources +I (6444) ts_source_mgr: Loaded 1 sources from SD card directory +I (5335) cmd_key: Registered command: key +I (5418) cmd_ssh: Registered command: ssh +I (5422) cmd_sftp: Registered command: sftp +I (5426) cmd_hosts: Registered command: hosts +I (5431) cmd_fs: File system commands registered: 9 succeeded, 0 failed +I (6531) cmd_gpio: GPIO command registered (high priority) +I (6533) ts_source_mgr: Exported 1 sources to directory: /sdcard/config/sources +I (6555) ts_source_mgr: Saved 1 sources to NVS and SD card +I (6557) ts_source_mgr: Deferred source loading complete: 1 sources +I (6558) ts_source_mgr: Starting loaded data sources... +I (6570) ts_source_mgr: Starting all data sources +I (6571) ts_source_mgr: Network ready, starting external sources +I (6573) ts_source_mgr: Starting Socket.IO source: agx-info +I (6535) cmd_ota: OTA command registered +I (6619) websocket_client: Started +I (6628) ts_source_mgr: SIO [agx-info] connection started +I (6575) ts_rule_engine: Deferred rule loading started +I (5561) cmd_pki: Registered 'pki' command +I (6659) cmd_auto: Command 'auto' registered +I (5565) cmd_register: Command registration complete: 24 succeeded, 0 failed +I (6664) ts_services: Starting console service... +I (5592) ts_console: Console task started +TianShanOS> I (6698) ts_config_pack: Successfully loaded encrypted config: /sdcard/config/ssh_hosts/rm01@10.10.99.98.tscfg +I (6673) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3.6-35B-A3B.json (281 bytes) +W (6711) ts_ssh_hosts_cfg: SD card import failed: ESP_ERR_NOT_FOUND +I (5604) ts_console: Console started +I (6720) ts_service: Service 'console' started in 779 ms +I (6722) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3-Embedding-0.6B.json (301 bytes) +I (6747) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3-Reranker-0.6B.json (297 bytes) +I (6751) ts_service: Starting service: webui +I (6757) ts_services: Initializing WebUI service... +I (6758) ts_config_pack: Loaded plain config: /sdcard/config/rules/drop.json (245 bytes) +I (6791) ts_config_pack: Loaded plain config: /sdcard/config/rules/Qwen3_8_27B_Quark_INT4_MTP3.json (324 bytes) +I (6806) ts_rule_engine: Deferred rule loading complete: 5 rules +I (7097) ts_action_mgr: Deferred action template loading started +I (7115) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3.6-35B-A3B.json (190 bytes) +I (7130) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3-Embedding-0.6B.json (205 bytes) +I (7149) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3-Reranker-0.6B.json (202 bytes) +I (7162) ts_config_pack: Loaded plain config: /sdcard/config/actions/drop.json (157 bytes) +I (7181) ts_config_pack: Loaded plain config: /sdcard/config/actions/Qwen3_8_27B_Quark_INT4_MTP3.json (272 bytes) +I (7186) ts_action_mgr: Loaded 5 templates from directory: /sdcard/config/actions +I (7198) ts_action_mgr: Loaded 5 action templates from SD card directory +I (7336) ts_services: Mounted www partition at /www (2541877/2884241 bytes) +I (6242) ts_webui: Initializing WebUI +I (6244) ts_http: HTTP server initialized +I (6246) ts_webui: WebUI initialized +I (7358) ts_action_mgr: Exported 5 templates to directory: /sdcard/config/actions +I (7363) ts_services: Starting WebUI service... +I (7365) ts_action_mgr: Saved 5 action templates to NVS and SD card +I (7377) ts_action_mgr: Deferred action template loading complete: 5 templates +I (6272) ts_http: HTTP server started on port 80 +I (6294) webui_api: Initializing API routes +I (6308) webui_api: API routes registered +I (6309) webui_ws: Initializing WebSocket with Terminal support +I (6311) webui_ws: Terminal buffer allocated in PSRAM (32768 bytes) +I (6323) webui_ws: Power policy event handler registered +I (6325) webui_ws: WebSocket handler registered at /ws +I (6336) ts_webui: WebUI started +I (7433) ts_services: WebUI server started on port 80 +I (7443) ts_service: Service 'webui' started in 686 ms +I (7445) ts_service: All services started in 5471 ms +I (7446) ts_core: TianShanOS started +I (7446) main: TianShanOS started successfully! +I (7457) main: Build: Sep 28 2026 18:02:10 +I (7458) ts_service: === Service Status === +I (7459) ts_service: Total: 12, Running: 12, Stopped: 0, Error: 0 +I (7470) ts_service: Startup time: 5471 ms +I (7471) ts_service: [SERVICE] automation - RUNNING (1622 ms) +I (7483) ts_service: [UI] console - RUNNING (779 ms) +I (7484) ts_service: [UI] webui - RUNNING (686 ms) +I (7485) ts_service: [SERVICE] https - RUNNING (21 ms) +I (7496) ts_service: [SERVICE] api - RUNNING (567 ms) +I (7497) ts_service: [SECURITY] security - RUNNING (320 ms) +I (7498) ts_service: [NETWORK] network - RUNNING (247 ms) +I (7510) ts_service: [DRIVER] power - RUNNING (123 ms) +I (7511) ts_service: [DRIVER] drivers - RUNNING (169 ms) +I (7523) ts_service: [DRIVER] led - RUNNING (178 ms) +I (7524) ts_service: [DRIVER] storage - RUNNING (276 ms) +I (7525) ts_service: [HAL] hal - RUNNING (90 ms) +I (7537) ts_service: ====================== +I (7537) main: Entering main loop... +I (7091) ts_device: LPMU startup detection: checking if LPMU is online... +I (7096) ts_device: LPMU detected online at 10.10.99.99, setting state to ON +I (41578) ts_config_pack: Loaded plain config: /sdcard/config/ui_widgets.json (480 bytes) +I (40486) api_ui: Loaded widgets from SD card +I (40488) api_ui: Loaded UI widgets config (source: sdcard) +I (42345) ts_security: Session created: e779c635 +I (42347) ts_auth: User root logged in (level 4, session e779c635) +I (44019) ts_config_pack: Loaded plain config: /sdcard/config/ui_widgets.json (480 bytes) +I (42926) api_ui: Loaded widgets from SD card +I (42928) api_ui: Loaded UI widgets config (source: sdcard) +I (44698) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (58401) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (59504) ts_ssh: SSH client initialized (libssh2 version: 1.10.1_DEV) +I (60314) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (60640) ts_shell: Interactive shell opened + +TianShanOS Console Commands +============================ + +[System] + hexdump + mv + cp + rm + mkdir + pwd + cd + cat + ls + dhcp + storage + service + system + lang + echo + clear + reboot + sysinfo + version + help + +[Configuration] + config + +[LED] + led + +[Fan] + fan + +[Network] + wifi + net + +[Device] + device + +[Debug] + log + free + tasks + +Use ' --help' for command details + +I (265867) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (267773) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (268157) ts_shell: Interactive shell opened +I (323032) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (324937) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (325162) ts_shell: Interactive shell opened +I (327228) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (329127) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (329389) ts_shell: Interactive shell opened +I (331546) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (333445) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (333670) ts_shell: Interactive shell opened +I (335813) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (337717) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (337919) ts_shell: Interactive shell opened +I (340026) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (341929) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (342173) ts_shell: Interactive shell opened +I (344146) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (346053) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (346175) ts_shell: Interactive shell opened +I (348122) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (350021) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (350184) ts_shell: Interactive shell opened +I (352274) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (354171) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (354436) ts_shell: Interactive shell opened +I (356493) webui_ws: update_log_stream_state: need_streaming=0, current=0 +I (358394) ts_known_hosts: Host key verified: 10.10.99.98:22 +I (358449) ts_shell: Interactive shell opened diff --git a/docs/repair/ssh-poll-stack/device-diagnostic/summary.json b/docs/repair/ssh-poll-stack/device-diagnostic/summary.json new file mode 100644 index 0000000..9c322d0 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-diagnostic/summary.json @@ -0,0 +1,11 @@ +{ + "minimum_sampled_hwm": 3984, + "serial_faults": [], + "final_pollers": [], + "manual_rounds": 1, + "automatic_successful_rounds": 9, + "failed_harness_attempts": 1, + "device_left_running": "formal candidate, restored and HTTP health verified", + "minimum_all_observed_hwm": 3644, + "evidence_boundary": "1 manual browser round + 9 native WS protocol rounds against real device and SSH host; not 10 browser keyboard rounds" +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/after-local.json b/docs/repair/ssh-poll-stack/device-final/after-local.json new file mode 100644 index 0000000..412c0b6 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/after-local.json @@ -0,0 +1,1138 @@ +{ + "state": { + "url": "http://10.10.99.97/#/terminal", + "login": false, + "Terminal": "function", + "FitAddon": "object", + "terminal": true, + "connected": true, + "ssh": false, + "text": "(base) rm01@agx:~$ \n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.55V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.46V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.23V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.37V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.34V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.50V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.29V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n^\\ (退出 SSH shell)\n正在结束 SSH 会话,请等待确认。\nSSH 会话已结束。\ntianshan> echo TIANSHAN_LOCAL_AFTER_J1\nTIANSHAN_LOCAL_AFTER_J1\ntianshan> " + }, + "requests": [ + { + "url": "http://10.10.99.97/", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/css/style.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-48.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/api.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/router.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/terminal.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/app.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.woff2", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/config/get?key=system.language", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ota/version", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/auth/login", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + } + ], + "errors": [], + "frames": [ + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "unsubscribe", + "topic": "system.dashboard" + }, + { + "direction": "received", + "type": "unsubscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --status" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --debug" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_connect", + "host": "10.10.99.98", + "port": 22, + "user": "rm01" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "e" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "c" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "h" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "o" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": " " + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "T" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "I" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "H" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "J" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "1" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "R" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "E" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "L" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "P" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "\r" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.29199981689453, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.29199981689453, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_disconnect" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "echo TIANSHAN_LOCAL_AFTER_J1" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + } + ] +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/browser-observer.cjs b/docs/repair/ssh-poll-stack/device-final/browser-observer.cjs new file mode 100644 index 0000000..7286d35 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/browser-observer.cjs @@ -0,0 +1,16 @@ +const {chromium}=require('/Users/massif/TianshanOS/tests/prompts/node_modules/playwright'); +const fs=require('fs'); +(async()=>{ + const out='/Users/massif/TianshanOS/output/playwright/pr42-final',origin='http://10.10.99.97'; + const browser=await chromium.launch({channel:'chrome',headless:false}); + const context=await browser.newContext({serviceWorkers:'block',viewport:{width:1280,height:900}}); + const requests=[],errors=[],frames=[]; + await context.route('**/*',r=>new URL(r.request().url()).origin===origin?r.continue():r.abort()); + const page=await context.newPage(); + page.on('request',r=>requests.push({url:r.url(),origin:new URL(r.url()).origin})); + page.on('pageerror',e=>errors.push(e.message)); + page.on('websocket',ws=>{ws.on('framereceived',f=>{try{const m=JSON.parse(f.payload);if(!['ssh_output','output'].includes(m.type))frames.push({direction:'received',...m});}catch{}});ws.on('framesent',f=>{try{const m=JSON.parse(f.payload);delete m.password;if(m.type==='terminal_input'&&m.data?.includes('--password'))m.data='[SSH connection command redacted]';frames.push({direction:'sent',...m});}catch{}});}); + await page.goto(origin+'/#/terminal'); + console.log('BROWSER_READY'); + setInterval(async()=>{try{const state=await page.evaluate(()=>({url:location.href,login:!document.getElementById('login-modal')?.classList.contains('hidden'),Terminal:typeof Terminal,FitAddon:typeof FitAddon,terminal:typeof webTerminal!=='undefined'&&!!webTerminal?.terminal,connected:typeof webTerminal!=='undefined'&&webTerminal?.connected,ssh:typeof webTerminal!=='undefined'&&webTerminal?.sshMode,text:document.querySelector('#terminal-container')?.innerText}));fs.writeFileSync(out+'/live.json',JSON.stringify({state,requests,errors,frames},null,2));}catch{}},1000); +})(); diff --git a/docs/repair/ssh-poll-stack/device-final/destroy.json b/docs/repair/ssh-poll-stack/device-final/destroy.json new file mode 100644 index 0000000..1650e79 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/destroy.json @@ -0,0 +1,2489 @@ +{ + "state": { + "url": "http://10.10.99.97/#/", + "login": false, + "Terminal": "function", + "FitAddon": "object", + "terminal": false + }, + "requests": [ + { + "url": "http://10.10.99.97/", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/css/style.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-48.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/api.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/router.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/terminal.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/app.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.woff2", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/config/get?key=system.language", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ota/version", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/auth/login", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ssh/hosts/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ssh/commands/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3.6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3.6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3-Embedding-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3-Embedding-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3-Reranker-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3-Reranker-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=drop", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=drop", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + } + ], + "errors": [], + "frames": [ + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "unsubscribe", + "topic": "system.dashboard" + }, + { + "direction": "received", + "type": "unsubscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --status" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --debug" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_connect", + "host": "10.10.99.98", + "port": 22, + "user": "rm01" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "e" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "c" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "h" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "o" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": " " + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "T" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "I" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "H" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "J" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "1" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "R" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "E" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "L" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "P" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "\r" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.29199981689453, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.29199981689453, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_disconnect" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "echo TIANSHAN_LOCAL_AFTER_J1" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 585, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 27 + }, + { + "id": 1, + "usage": 13 + } + ], + "total_usage": 20, + "total_runtime": 585609736, + "task_count": 24 + }, + "memory": { + "free_heap": 7636428, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579208, + "allocated": 790972, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 585611 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.337600708007812, + "adc_raw": 2105, + "timestamp_ms": 586165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.337600708007812 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 584526 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.5, + "slope_c_per_min": -0.4000000059604645, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 586, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 25 + }, + { + "id": 1, + "usage": 3 + } + ], + "total_usage": 14, + "total_runtime": 586643040, + "task_count": 24 + }, + "memory": { + "free_heap": 7632408, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8369732, + "free": 7574100, + "allocated": 795632, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 586645 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.51999855041504, + "adc_raw": 2125, + "timestamp_ms": 587165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.51999855041504 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 585553 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.8, + "slope_c_per_min": 0, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 587, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 39 + }, + { + "id": 1, + "usage": 36 + } + ], + "total_usage": 37, + "total_runtime": 587693752, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579208, + "allocated": 790972, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 587695 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.44019889831543, + "adc_raw": 2117, + "timestamp_ms": 588166 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.44019889831543 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 586577 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 20, + "target_duty": 20, + "rpm": 0, + "temperature": 52.9, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.9, + "guard_temperature": 52.9, + "predicted_temperature": 52.9, + "slope_c_per_min": 0, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.9000015258789, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 588, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 23 + }, + { + "id": 1, + "usage": 1 + } + ], + "total_usage": 12, + "total_runtime": 588721054, + "task_count": 24 + }, + "memory": { + "free_heap": 7636436, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579216, + "allocated": 790964, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 588722 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.337600708007812, + "adc_raw": 2107, + "timestamp_ms": 589165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.337600708007812 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 587602 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 53, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 53, + "guard_temperature": 53, + "predicted_temperature": 53.1, + "slope_c_per_min": 0.20000000298023224, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 53, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 589, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 23 + }, + { + "id": 1, + "usage": 6 + } + ], + "total_usage": 14, + "total_runtime": 589735957, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579216, + "allocated": 790964, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 589737 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.83919906616211, + "adc_raw": 2157, + "timestamp_ms": 590165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.83919906616211 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 588627 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.5, + "slope_c_per_min": -0.4000000059604645, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/health-assets.json b/docs/repair/ssh-poll-stack/device-final/health-assets.json new file mode 100644 index 0000000..cae5fcd --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/health-assets.json @@ -0,0 +1,249 @@ +{ + "system/info": { + "code": 0, + "data": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 614026 + } + }, + "system/tasks": { + "code": 0, + "data": { + "tasks": [ + { + "name": "httpd", + "priority": 5, + "stack_hwm": 1144, + "core": 1, + "state": "running" + }, + { + "name": "IDLE0", + "priority": 0, + "stack_hwm": 624, + "core": 0, + "state": "ready" + }, + { + "name": "IDLE1", + "priority": 0, + "stack_hwm": 696, + "core": 1, + "state": "ready" + }, + { + "name": "power_policy", + "priority": 5, + "stack_hwm": 636, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_auto", + "priority": 5, + "stack_hwm": 2032, + "core": 1, + "state": "blocked" + }, + { + "name": "tiT", + "priority": 18, + "stack_hwm": 1580, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "sio_agx-info", + "priority": 5, + "stack_hwm": 1792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "https_coord", + "priority": 5, + "stack_hwm": 5432, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "websocket_task", + "priority": 5, + "stack_hwm": 1340, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "action_exec", + "priority": 5, + "stack_hwm": 13008, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "w5500_tsk", + "priority": 15, + "stack_hwm": 2792, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "main", + "priority": 1, + "stack_hwm": 536, + "core": 0, + "state": "blocked" + }, + { + "name": "power_monitor", + "priority": 5, + "stack_hwm": 1956, + "core": 0, + "state": "blocked" + }, + { + "name": "ts_console", + "priority": 5, + "stack_hwm": 1964, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "dhcp_evt", + "priority": 5, + "stack_hwm": 900, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "ipc1", + "priority": 24, + "stack_hwm": 528, + "core": 1, + "state": "suspended" + }, + { + "name": "ipc0", + "priority": 24, + "stack_hwm": 392, + "core": 0, + "state": "suspended" + }, + { + "name": "ws_telemetry", + "priority": 2, + "stack_hwm": 2116, + "core": 0, + "state": "suspended" + }, + { + "name": "ts_event", + "priority": 5, + "stack_hwm": 904, + "core": 1, + "state": "blocked" + }, + { + "name": "esp_timer", + "priority": 22, + "stack_hwm": 2488, + "core": 0, + "state": "suspended" + }, + { + "name": "led_render", + "priority": 5, + "stack_hwm": 1364, + "core": 0, + "state": "blocked" + }, + { + "name": "sys_evt", + "priority": 20, + "stack_hwm": 1684, + "core": 0, + "state": "blocked" + }, + { + "name": "Tmr Svc", + "priority": 1, + "stack_hwm": 800, + "core": 2147483647, + "state": "blocked" + }, + { + "name": "httpd", + "priority": 5, + "stack_hwm": 15152, + "core": 2147483647, + "state": "blocked" + } + ], + "count": 24 + } + }, + "power/status": { + "code": 0, + "data": { + "voltage": { + "supply_v": 20.48579978942871, + "adc_raw": 2121, + "timestamp_ms": 614165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.48579978942871 + }, + "stats": { + "samples": 119, + "avg_voltage_v": 20.466068267822266, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 612892 + }, + "monitoring_active": true + } + }, + "vendor": { + "xterm.min.js": { + "sha256": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "size": 283670, + "matches_source": true + }, + "xterm.css": { + "sha256": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "size": 5383, + "matches_source": true + }, + "fit.min.js": { + "sha256": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "size": 1789, + "matches_source": true + } + } +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/j1-active.json b/docs/repair/ssh-poll-stack/device-final/j1-active.json new file mode 100644 index 0000000..90e64c5 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/j1-active.json @@ -0,0 +1,560 @@ +{ + "state": { + "url": "http://10.10.99.97/#/terminal", + "login": false, + "Terminal": "function", + "FitAddon": "object", + "terminal": true, + "connected": true, + "ssh": true, + "text": " 连接…\nSSH 交互式终端已就绪。\n(按 Ctrl+\\ 退出 SSH shell)\n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\nWelcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.148-tegra aarch64)\n * Documentation: https://help.ubuntu.com\n * Management: https://landscape.canonical.com\n * Support: https://ubuntu.com/pro\nThis system has been minimized by removing packages and content that are\nnot required on a system that users do not log into.\nTo restore this content, you can run the 'unminimize' command.\nLast login: Mon Sep 28 10:31:25 2026 from 10.10.99.97\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n(base) rm01@agx:~$ \n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.50V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.55V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.43V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n " + }, + "requests": [ + { + "url": "http://10.10.99.97/", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/css/style.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-48.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/api.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/router.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/terminal.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/app.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.woff2", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/config/get?key=system.language", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ota/version", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/auth/login", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + } + ], + "errors": [], + "frames": [ + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "unsubscribe", + "topic": "system.dashboard" + }, + { + "direction": "received", + "type": "unsubscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --status" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --debug" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_connect", + "host": "10.10.99.98", + "port": 22, + "user": "rm01" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + } + ] +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/j1-echo.json b/docs/repair/ssh-poll-stack/device-final/j1-echo.json new file mode 100644 index 0000000..f2968fb --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/j1-echo.json @@ -0,0 +1,991 @@ +{ + "state": { + "url": "http://10.10.99.97/#/terminal", + "login": false, + "Terminal": "function", + "FitAddon": "object", + "terminal": true, + "connected": true, + "ssh": true, + "text": "📊 [调试] NORMAL | 电压: 20.52V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.30V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.49V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.52V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.28V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.50V | 倒计时: 0s\necho TIANSHAN_J1_REAL_PASS\nTIANSHAN_J1_REAL_PASS\n(base) rm01@agx:~$ \n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.55V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.46V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.44V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.23V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.37V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.34V | 倒计时: 0s\n📊 [调试] NORMAL | 电压: 20.50V | 倒计时: 0s\n " + }, + "requests": [ + { + "url": "http://10.10.99.97/", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/css/style.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-48.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/api.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/router.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/terminal.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/app.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.woff2", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/config/get?key=system.language", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ota/version", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/auth/login", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + } + ], + "errors": [], + "frames": [ + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "unsubscribe", + "topic": "system.dashboard" + }, + { + "direction": "received", + "type": "unsubscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --status" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --debug" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_connect", + "host": "10.10.99.98", + "port": 22, + "user": "rm01" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "e" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "c" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "h" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "o" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": " " + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "T" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "I" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "H" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "J" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "1" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "R" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "E" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "L" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "P" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "\r" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + } + ] +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/network.json b/docs/repair/ssh-poll-stack/device-final/network.json new file mode 100644 index 0000000..eb3bf0c --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/network.json @@ -0,0 +1,339 @@ +{ + "requests": [ + { + "url": "http://10.10.99.97/", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/css/style.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-48.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/api.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/router.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/terminal.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/app.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.woff2", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/config/get?key=system.language", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ota/version", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/auth/login", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ssh/hosts/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ssh/commands/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3.6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3.6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3-Embedding-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3-Embedding-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3-Reranker-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3-Reranker-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=drop", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=drop", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + } + ], + "errors": [], + "externalRequests": 0, + "freshContext": true, + "serviceWorkers": "block", + "originAllowlist": [ + "http://10.10.99.97" + ] +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/device-final/reentry.json b/docs/repair/ssh-poll-stack/device-final/reentry.json new file mode 100644 index 0000000..ecea624 --- /dev/null +++ b/docs/repair/ssh-poll-stack/device-final/reentry.json @@ -0,0 +1,3753 @@ +{ + "state": { + "url": "http://10.10.99.97/#/terminal", + "login": false, + "Terminal": "function", + "FitAddon": "object", + "terminal": true, + "connected": true, + "ssh": false, + "text": "╔══════════════════════════════════════════╗\n║ TianshanOS Web Terminal ║\n╚══════════════════════════════════════════╝\n正在连接到设备...\n已连接到设备\n输入 help 查看可用命令\ntianshan> " + }, + "requests": [ + { + "url": "http://10.10.99.97/", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/css/style.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-48.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/api.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/router.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/terminal.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/app.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/fonts/remixicon.woff2", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/config/get?key=system.language", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ota/version", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/auth/login", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/time/info", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/system/memory", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/network/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/power/protection/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/fan/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/service/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/led/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/usb/status", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ui/widgets/get", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/status?device=agx", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ssh/hosts/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/ssh/commands/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/list", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3.6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3.6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3-Embedding-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3-Embedding-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3-Reranker-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3-Reranker-0.6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=drop", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=drop", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/rules/get?id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/actions/get?id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_6-35B-A3B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Embedding-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3-Reranker-0_6B", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/services/status?command_id=Qwen3_8_27B_Quark_INT4_MTP3", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/automation/variables/list?include_meta=false", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/api/v1/device/ping", + "origin": "http://10.10.99.97" + }, + { + "url": "http://10.10.99.97/images/tslogo-32.png", + "origin": "http://10.10.99.97" + } + ], + "errors": [], + "frames": [ + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "unsubscribe", + "topic": "system.dashboard" + }, + { + "direction": "received", + "type": "unsubscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "received", + "type": "session_closed", + "reason": "Another terminal session requested" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --status" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "voltprot --debug" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_connect", + "host": "10.10.99.98", + "port": 22, + "user": "rm01" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.428800582885742, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.30340003967285, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.51999855041504, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.28059959411621, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "e" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "c" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "h" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "o" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": " " + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "T" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "I" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "H" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "N" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "J" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "1" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "R" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "E" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "L" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "_" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "P" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "A" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "S" + }, + { + "direction": "sent", + "type": "ssh_input", + "data": "\r" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.55419921875, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.46299934387207, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.23499870300293, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.37179946899414, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.337600708007812, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.49720001220703, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.48579978942871, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.29199981689453, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.29199981689453, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "received", + "type": "power_event", + "state": "NORMAL", + "voltage": 20.44019889831543, + "countdown": 0, + "protection_count": 0, + "event": "debug_tick" + }, + { + "direction": "sent", + "type": "ssh_disconnect" + }, + { + "direction": "received", + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + { + "direction": "received", + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "subscribe", + "events": [ + "*" + ] + }, + { + "direction": "sent", + "type": "terminal_input", + "data": "echo TIANSHAN_LOCAL_AFTER_J1" + }, + { + "direction": "received", + "type": "done", + "code": 0 + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "terminal_stop" + }, + { + "direction": "sent", + "type": "subscribe", + "topic": "system.dashboard", + "params": { + "interval": 1000 + } + }, + { + "direction": "received", + "type": "subscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 585, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 27 + }, + { + "id": 1, + "usage": 13 + } + ], + "total_usage": 20, + "total_runtime": 585609736, + "task_count": 24 + }, + "memory": { + "free_heap": 7636428, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579208, + "allocated": 790972, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 585611 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.337600708007812, + "adc_raw": 2105, + "timestamp_ms": 586165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.337600708007812 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 584526 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.5, + "slope_c_per_min": -0.4000000059604645, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 586, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 25 + }, + { + "id": 1, + "usage": 3 + } + ], + "total_usage": 14, + "total_runtime": 586643040, + "task_count": 24 + }, + "memory": { + "free_heap": 7632408, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8369732, + "free": 7574100, + "allocated": 795632, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 586645 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.51999855041504, + "adc_raw": 2125, + "timestamp_ms": 587165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.51999855041504 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 585553 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.8, + "slope_c_per_min": 0, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 587, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 39 + }, + { + "id": 1, + "usage": 36 + } + ], + "total_usage": 37, + "total_runtime": 587693752, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579208, + "allocated": 790972, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 587695 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.44019889831543, + "adc_raw": 2117, + "timestamp_ms": 588166 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.44019889831543 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 586577 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 20, + "target_duty": 20, + "rpm": 0, + "temperature": 52.9, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.9, + "guard_temperature": 52.9, + "predicted_temperature": 52.9, + "slope_c_per_min": 0, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.9000015258789, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 588, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 23 + }, + { + "id": 1, + "usage": 1 + } + ], + "total_usage": 12, + "total_runtime": 588721054, + "task_count": 24 + }, + "memory": { + "free_heap": 7636436, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579216, + "allocated": 790964, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 588722 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.337600708007812, + "adc_raw": 2107, + "timestamp_ms": 589165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.337600708007812 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 587602 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 53, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 53, + "guard_temperature": 53, + "predicted_temperature": 53.1, + "slope_c_per_min": 0.20000000298023224, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 53, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 589, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 23 + }, + { + "id": 1, + "usage": 6 + } + ], + "total_usage": 14, + "total_runtime": 589735957, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579216, + "allocated": 790964, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 589737 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.83919906616211, + "adc_raw": 2157, + "timestamp_ms": 590165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.83919906616211 + }, + "stats": { + "samples": 114, + "avg_voltage_v": 20.465604782104492, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 588627 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.5, + "slope_c_per_min": -0.4000000059604645, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 590, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 26 + }, + { + "id": 1, + "usage": 7 + } + ], + "total_usage": 16, + "total_runtime": 590758690, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579208, + "allocated": 790972, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 590760 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.63399887084961, + "adc_raw": 2137, + "timestamp_ms": 591165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.63399887084961 + }, + "stats": { + "samples": 115, + "avg_voltage_v": 20.46498680114746, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 589652 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 53, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 53, + "guard_temperature": 53, + "predicted_temperature": 53, + "slope_c_per_min": 0, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 53, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 591, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 22 + }, + { + "id": 1, + "usage": 1 + } + ], + "total_usage": 11, + "total_runtime": 591773691, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579208, + "allocated": 790972, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 591775 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.48579978942871, + "adc_raw": 2121, + "timestamp_ms": 592165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.48579978942871 + }, + "stats": { + "samples": 115, + "avg_voltage_v": 20.46498680114746, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 590677 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.6, + "slope_c_per_min": -0.20000000298023224, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 592, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 24 + }, + { + "id": 1, + "usage": 6 + } + ], + "total_usage": 15, + "total_runtime": 592788696, + "task_count": 24 + }, + "memory": { + "free_heap": 7636440, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579212, + "allocated": 790968, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 592790 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.48579978942871, + "adc_raw": 2120, + "timestamp_ms": 593165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.48579978942871 + }, + "stats": { + "samples": 115, + "avg_voltage_v": 20.46498680114746, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 591702 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.8, + "slope_c_per_min": 0, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 593, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 26 + }, + { + "id": 1, + "usage": 7 + } + ], + "total_usage": 16, + "total_runtime": 593803754, + "task_count": 24 + }, + "memory": { + "free_heap": 7636436, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579216, + "allocated": 790964, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 593805 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.48579978942871, + "adc_raw": 2121, + "timestamp_ms": 594165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.48579978942871 + }, + "stats": { + "samples": 115, + "avg_voltage_v": 20.46498680114746, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 592556 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.9, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.9, + "guard_temperature": 52.9, + "predicted_temperature": 53, + "slope_c_per_min": 0.20000000298023224, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.9000015258789, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "received", + "type": "data", + "topic": "system.dashboard", + "timestamp": 594, + "data": { + "cpu": { + "cores": [ + { + "id": 0, + "usage": 24 + }, + { + "id": 1, + "usage": 8 + } + ], + "total_usage": 16, + "total_runtime": 594819762, + "task_count": 24 + }, + "memory": { + "free_heap": 7636432, + "min_free_heap": 7485660, + "internal": { + "total": 308043, + "free": 72755, + "allocated": 235288, + "largest_block": 31744 + }, + "psram": { + "total": 8370180, + "free": 7579216, + "allocated": 790964, + "largest_block": 7471104 + } + }, + "info": { + "app": { + "name": "TianShanOS", + "version": "0.5.2+3a19128d.09281801", + "idf_version": "v5.5.2", + "compile_time": "18:01:50", + "compile_date": "Sep 28 2026" + }, + "chip": { + "model": "ESP32-S3", + "cores": 2, + "revision": 2, + "features": [ + "WiFi", + "BLE" + ] + }, + "flash_size": 16777216, + "uptime_ms": 594821 + }, + "network": { + "hostname": "TianshanOS", + "ethernet": { + "status": "connected", + "link_up": true, + "ip": "10.10.99.97", + "netmask": "255.255.255.0", + "gateway": "10.10.99.100", + "dns1": "8.8.8.8", + "mac": "20:6e:f1:a1:d5:8f" + }, + "wifi_sta": { + "status": "down", + "connected": false + }, + "wifi_ap": { + "status": "down", + "sta_count": 0 + } + }, + "power": { + "voltage": { + "supply_v": 20.48579978942871, + "adc_raw": 2120, + "timestamp_ms": 595165 + }, + "power_chip": { + "valid": false, + "voltage_v": 20, + "current_a": 4.5, + "power_w": 90, + "crc_valid": false + }, + "protection": { + "running": true, + "state": "正常运行", + "countdown_sec": 0, + "current_voltage_v": 20.48579978942871 + }, + "stats": { + "samples": 115, + "avg_voltage_v": 20.46498680114746, + "avg_current_a": 0, + "avg_power_w": 0, + "uptime_ms": 593583 + }, + "monitoring_active": true + }, + "fan": { + "fans": [ + { + "id": 0, + "mode": "auto", + "duty": 21, + "target_duty": 21, + "rpm": 0, + "temperature": 52.8, + "enabled": true, + "running": true, + "fault": false, + "control_temperature": 52.8, + "guard_temperature": 52.8, + "predicted_temperature": 52.6, + "slope_c_per_min": -0.20000000298023224, + "controller_gain": 0.75, + "cooling_response": 0, + "auto_state": "active", + "guard_active": false, + "temp_stale": false + } + ], + "temperature": 52.79999923706055, + "temp_valid": true, + "temp_source": "agx-info.temperature.tj" + }, + "services": { + "total": 12, + "running": 12, + "services": [ + { + "name": "automation", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 2397, + "start_duration_ms": 1726 + }, + { + "name": "console", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 4864, + "start_duration_ms": 521 + }, + { + "name": "webui", + "state": "RUNNING", + "phase": "UI", + "healthy": true, + "start_time_ms": 5398, + "start_duration_ms": 438 + }, + { + "name": "https", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4133, + "start_duration_ms": 17 + }, + { + "name": "api", + "state": "RUNNING", + "phase": "SERVICE", + "healthy": true, + "start_time_ms": 4293, + "start_duration_ms": 372 + }, + { + "name": "security", + "state": "RUNNING", + "phase": "SECURITY", + "healthy": true, + "start_time_ms": 2109, + "start_duration_ms": 267 + }, + { + "name": "network", + "state": "RUNNING", + "phase": "NETWORK", + "healthy": true, + "start_time_ms": 1867, + "start_duration_ms": 223 + }, + { + "name": "power", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1005, + "start_duration_ms": 123 + }, + { + "name": "drivers", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1137, + "start_duration_ms": 169 + }, + { + "name": "led", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1314, + "start_duration_ms": 178 + }, + { + "name": "storage", + "state": "RUNNING", + "phase": "DRIVER", + "healthy": true, + "start_time_ms": 1508, + "start_duration_ms": 263 + }, + { + "name": "hal", + "state": "RUNNING", + "phase": "HAL", + "healthy": true, + "start_time_ms": 898, + "start_duration_ms": 89 + } + ] + } + } + }, + { + "direction": "sent", + "type": "unsubscribe", + "topic": "system.dashboard" + }, + { + "direction": "received", + "type": "unsubscribed", + "topic": "system.dashboard", + "success": true + }, + { + "direction": "sent", + "type": "terminal_start" + }, + { + "direction": "received", + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + }, + { + "direction": "sent", + "type": "ping" + }, + { + "direction": "received", + "type": "pong" + } + ] +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/diagnostic/assets.json b/docs/repair/ssh-poll-stack/diagnostic/assets.json new file mode 100644 index 0000000..5204409 --- /dev/null +++ b/docs/repair/ssh-poll-stack/diagnostic/assets.json @@ -0,0 +1,41 @@ +{ + "index.html": { + "source_sha256": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "optimized_sha256": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "gzip_sha256": "afd701f9af947c094ce29bee09fec963c1e01047a51bed1af8ba87433b42c2c6", + "optimized_bytes": 26676 + }, + "js/terminal.js": { + "source_sha256": "5d77a7181b6127699e098f22d3c872f5e31daaa700436b6fa928f34b6aa33e52", + "optimized_sha256": "6759587f527a0c37aaf8b13f6b5ffc017a452954cd23b780b5d6254488f939dc", + "gzip_sha256": "5e752fd41510e42f7fc71af8ae4c6993c1bdae9842e1dee3e9469cb297d7b0df", + "optimized_bytes": 20066 + }, + "js/lang/zh-CN.js": { + "source_sha256": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "optimized_sha256": "81b0fed5b0ac73d51d9c37204c9f62e035a79bbf5b5610d37fc8a936faf9fd64", + "gzip_sha256": "f140439b1f907b4842f8d100111281625a643f08b3f802806ba66df959742085", + "optimized_bytes": 137314 + }, + "js/lang/en-US.js": { + "source_sha256": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "optimized_sha256": "e9963046086616fecc9ba662df94e736a98c1430865e0caa47292b3690ca0ad0", + "gzip_sha256": "a7f454b4aa15865cbf8616df3de1a8b382a2c45a695816f51790a41c0a9e89d1", + "optimized_bytes": 143161 + }, + "build": { + "TianShanOS.bin": { + "sha256": "a217c5932e97d0db90f7032abba274c218c327e0725c80f278898c8dcc295f85", + "bytes": 2465504 + }, + "www.bin": { + "sha256": "30e4c70f01b60ce1d51c6392a3f2b4d196d4886cf554c0167db9554c1beecb50", + "bytes": 3145728 + }, + "TianShanOS.elf": { + "sha256": "e6fa1eadbce3940ba88b0431d0367154082abcc4bcacbd634a43028e06aaf7ff", + "bytes": 18857336 + } + }, + "spiffs_regeneration": "byte-identical from verified optimized directory" +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/diagnostic/build.log b/docs/repair/ssh-poll-stack/diagnostic/build.log new file mode 100644 index 0000000..9c2a3f9 --- /dev/null +++ b/docs/repair/ssh-poll-stack/diagnostic/build.log @@ -0,0 +1,1698 @@ +Checking "python3" ... +Python 3.12.4 +"python3" has been detected +Activating ESP-IDF 5.5 +Setting IDF_PATH to '/Users/massif/esp/v5.5.2/esp-idf'. +* Checking python version ... 3.12.4 +* Checking python dependencies ... OK +* Deactivating the current ESP-IDF environment (if any) ... OK +* Establishing a new ESP-IDF environment ... OK +* Identifying shell ... zsh +* Detecting outdated tools in system ... Found tools that are not used by active ESP-IDF version. +For removing old versions of riscv32-esp-elf, cmake, xtensa-esp-elf, openocd-esp32, esp-rom-elfs, xtensa-esp-elf-gdb, riscv32-esp-elf-gdb use command 'python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall' +To free up even more space, remove installation packages of those tools. +Use option python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall --remove-archives. +* Shell completion ... Autocompletion code generated + +Done! You can now compile ESP-IDF projects. +Go to the project directory and run: + + idf.py build +ESP-IDF v5.5.2 +Executing action: all (aliases: build) +Running cmake in directory /private/tmp/tianshan-ssh-stack-diagnostic/build +Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DPYTHON=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python -DESP_PLATFORM=1 -DSDKCONFIG=/tmp/tianshan-ssh-stack-diagnostic/sdkconfig -DCCACHE_ENABLE=0 /Users/massif/TianshanOS"... +-- Found Python3: /opt/anaconda3/bin/python3.12 (found version "3.12.4") found components: Interpreter +-- IDF_TARGET is not set, guessed 'esp32s3' from sdkconfig '/tmp/tianshan-ssh-stack-diagnostic/sdkconfig' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +NOTICE: +Following dependencies have new versions available: +Dependency "espressif/libpng": "1.6.54" -> "1.6.58~2" +Dependency "espressif/mdns": "1.9.1" -> "1.13.1" +Dependency "espressif/zlib": "1.3.1" -> "1.3.2~1" +Consider running "idf.py update-dependencies" to update your lock file. +NOTICE: Processing 7 dependencies: +NOTICE: [1/7] espressif/esp_jpeg (1.3.1) +NOTICE: [2/7] espressif/esp_websocket_client (1.5.0) +NOTICE: [3/7] espressif/led_strip (3.0.3) +NOTICE: [4/7] espressif/libpng (1.6.54) +NOTICE: [5/7] espressif/mdns (1.9.1) +NOTICE: [6/7] espressif/zlib (1.3.1) +NOTICE: [7/7] idf (5.5.2) +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-ssh-stack-diagnostic/sdkconfig +Loading defaults file /Users/massif/TianshanOS/sdkconfig.defaults... +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:54 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:56 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:64 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:66 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:82 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:84 line was updated to # === L2 NVS 加密配置(HMAC 方案)===n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:159 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:161 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:170 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:172 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:182 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:184 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:193 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:195 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:227 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpujgd4r60:229 line was updated to # ============================================================================n +-- Compiler supported targets: xtensa-esp-elf +-- Found Python3: /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python (found version "3.12.4") found components: Interpreter +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS - Success +-- USING O3 +-- App "TianShanOS" version: 0.5.2+3a19128d.09281801 +-- Adding linker script /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/esp_system/ld/memory.ld +-- Adding linker script /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/esp_system/ld/sections.ld.in +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Web optimization enabled (minify + gzip) +-- Components: app_trace app_update bootloader bootloader_support bt ch405labs_esp_libssh2 cmock console cxx driver efuse esp-tls esp_adc esp_app_format esp_bootloader_format esp_coex esp_common esp_driver_ana_cmpr esp_driver_bitscrambler esp_driver_cam esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_isp esp_driver_jpeg esp_driver_ledc esp_driver_mcpwm esp_driver_parlio esp_driver_pcnt esp_driver_ppa esp_driver_rmt esp_driver_sdio esp_driver_sdm esp_driver_sdmmc esp_driver_sdspi esp_driver_spi esp_driver_touch_sens esp_driver_tsens esp_driver_twai esp_driver_uart esp_driver_usb_serial_jtag esp_eth esp_event esp_gdbstub esp_hid esp_http_client esp_http_server esp_https_ota esp_https_server esp_hw_support esp_lcd esp_local_ctrl esp_mm esp_netif esp_netif_stack esp_partition esp_phy esp_pm esp_psram esp_ringbuf esp_rom esp_security esp_system esp_timer esp_vfs_console esp_wifi espcoredump espressif__esp_jpeg espressif__esp_websocket_client espressif__led_strip espressif__libpng espressif__mdns espressif__zlib esptool_py fatfs freertos hal heap http_parser idf_test ieee802154 json log lwip main mbedtls mqtt newlib nvs_flash nvs_sec_provider openthread partition_table perfmon protobuf-c protocomm pthread rt sdmmc soc spi_flash spiffs tcp_transport touch_element ts_api ts_auth_layout ts_automation ts_cert ts_config ts_config_pack ts_console ts_core ts_drivers ts_event ts_hal ts_https ts_jsonpath ts_led ts_log ts_mempool ts_net ts_ota ts_pki_client ts_security ts_service ts_storage ts_webui ulp unity usb vfs wear_levelling wifi_provisioning wpa_supplicant xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/app_trace /Users/massif/esp/v5.5.2/esp-idf/components/app_update /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/bt /Users/massif/TianshanOS/components/ch405labs_esp_libssh2 /Users/massif/esp/v5.5.2/esp-idf/components/cmock /Users/massif/esp/v5.5.2/esp-idf/components/console /Users/massif/esp/v5.5.2/esp-idf/components/cxx /Users/massif/esp/v5.5.2/esp-idf/components/driver /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp-tls /Users/massif/esp/v5.5.2/esp-idf/components/esp_adc /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_coex /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ana_cmpr /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_bitscrambler /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_cam /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_dac /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gpio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gptimer /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2c /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2s /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_isp /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_jpeg /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ledc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_mcpwm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_parlio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_pcnt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ppa /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_rmt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdspi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_spi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_touch_sens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_tsens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_twai /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_uart /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_usb_serial_jtag /Users/massif/esp/v5.5.2/esp-idf/components/esp_eth /Users/massif/esp/v5.5.2/esp-idf/components/esp_event /Users/massif/esp/v5.5.2/esp-idf/components/esp_gdbstub /Users/massif/esp/v5.5.2/esp-idf/components/esp_hid /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_client /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_ota /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_lcd /Users/massif/esp/v5.5.2/esp-idf/components/esp_local_ctrl /Users/massif/esp/v5.5.2/esp-idf/components/esp_mm /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif_stack /Users/massif/esp/v5.5.2/esp-idf/components/esp_partition /Users/massif/esp/v5.5.2/esp-idf/components/esp_phy /Users/massif/esp/v5.5.2/esp-idf/components/esp_pm /Users/massif/esp/v5.5.2/esp-idf/components/esp_psram /Users/massif/esp/v5.5.2/esp-idf/components/esp_ringbuf /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esp_timer /Users/massif/esp/v5.5.2/esp-idf/components/esp_vfs_console /Users/massif/esp/v5.5.2/esp-idf/components/esp_wifi /Users/massif/esp/v5.5.2/esp-idf/components/espcoredump /Users/massif/TianshanOS/managed_components/espressif__esp_jpeg /Users/massif/TianshanOS/managed_components/espressif__esp_websocket_client /Users/massif/TianshanOS/managed_components/espressif__led_strip /Users/massif/TianshanOS/managed_components/espressif__libpng /Users/massif/TianshanOS/managed_components/espressif__mdns /Users/massif/TianshanOS/managed_components/espressif__zlib /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/fatfs /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/heap /Users/massif/esp/v5.5.2/esp-idf/components/http_parser /Users/massif/esp/v5.5.2/esp-idf/components/idf_test /Users/massif/esp/v5.5.2/esp-idf/components/ieee802154 /Users/massif/esp/v5.5.2/esp-idf/components/json /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/lwip /Users/massif/TianshanOS/main /Users/massif/esp/v5.5.2/esp-idf/components/mbedtls /Users/massif/esp/v5.5.2/esp-idf/components/mqtt /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/nvs_flash /Users/massif/esp/v5.5.2/esp-idf/components/nvs_sec_provider /Users/massif/esp/v5.5.2/esp-idf/components/openthread /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/perfmon /Users/massif/esp/v5.5.2/esp-idf/components/protobuf-c /Users/massif/esp/v5.5.2/esp-idf/components/protocomm /Users/massif/esp/v5.5.2/esp-idf/components/pthread /Users/massif/esp/v5.5.2/esp-idf/components/rt /Users/massif/esp/v5.5.2/esp-idf/components/sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/spiffs /Users/massif/esp/v5.5.2/esp-idf/components/tcp_transport /Users/massif/esp/v5.5.2/esp-idf/components/touch_element /Users/massif/TianshanOS/components/ts_api /Users/massif/TianshanOS/components/ts_auth_layout /Users/massif/TianshanOS/components/ts_automation /Users/massif/TianshanOS/components/ts_cert /Users/massif/TianshanOS/components/ts_core/ts_config /Users/massif/TianshanOS/components/ts_config_pack /Users/massif/TianshanOS/components/ts_console /Users/massif/TianshanOS/components/ts_core /Users/massif/TianshanOS/components/ts_drivers /Users/massif/TianshanOS/components/ts_core/ts_event /Users/massif/TianshanOS/components/ts_hal /Users/massif/TianshanOS/components/ts_https /Users/massif/TianshanOS/components/ts_jsonpath /Users/massif/TianshanOS/components/ts_led /Users/massif/TianshanOS/components/ts_core/ts_log /Users/massif/TianshanOS/components/ts_mempool /Users/massif/TianshanOS/components/ts_net /Users/massif/TianshanOS/components/ts_ota /Users/massif/TianshanOS/components/ts_pki_client /Users/massif/TianshanOS/components/ts_security /Users/massif/TianshanOS/components/ts_core/ts_service /Users/massif/TianshanOS/components/ts_storage /Users/massif/TianshanOS/components/ts_webui /Users/massif/esp/v5.5.2/esp-idf/components/ulp /Users/massif/esp/v5.5.2/esp-idf/components/unity /Users/massif/esp/v5.5.2/esp-idf/components/usb /Users/massif/esp/v5.5.2/esp-idf/components/vfs /Users/massif/esp/v5.5.2/esp-idf/components/wear_levelling /Users/massif/esp/v5.5.2/esp-idf/components/wifi_provisioning /Users/massif/esp/v5.5.2/esp-idf/components/wpa_supplicant /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- +-- ╔═══════════════════════════════════════════════════════════╗ +-- ║ TianShanOS v0.5.2+3a19128d.09281801 ║ +-- ║ ESP32 Rack Management Operating System ║ +-- ╚═══════════════════════════════════════════════════════════╝ +-- +-- Version: 0.5.2+3a19128d.09281801 +-- Major: 0 +-- Minor: 5 +-- Patch: 2 +-- Build: 3a19128d.09281801 +-- +-- Target: esp32s3 +-- Build type: +-- +-- Configuring done (9.5s) +-- Generating done (2.3s) +-- Build files have been written to: /tmp/tianshan-ssh-stack-diagnostic/build +Running ninja in directory /private/tmp/tianshan-ssh-stack-diagnostic/build +Executing "ninja all"... +[1/1344] Generating project_elf_src_esp32s3.c +[2/1344] Generating ../../ota_data_initial.bin +[3/1344] Generating /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/esp_system/ld/memory.ld linker script... +[4/1344] Generating /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/esp_system/ld/sections.ld.in linker script... +[5/1344] Copying web assets to build directory +[6/1344] Generating ../../partition_table/partition-table.bin +Partition table binary generated. Contents: +******************************************************************************* +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs,data,nvs,0x9000,48K, +nvs_keys,data,nvs_keys,0x15000,4K, +otadata,data,ota,0x16000,8K, +phy_init,data,phy,0x18000,4K, +ota_0,app,ota_0,0x20000,3M, +ota_1,app,ota_1,0x320000,3M, +storage,data,spiffs,0x620000,512K, +www,data,spiffs,0x6a0000,3M, +fatfs,data,fat,0x9a0000,64K, +******************************************************************************* +[7/1344] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_utils.c.obj +[8/1344] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_header.c.obj +[9/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_sess.c.obj +[10/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/util/ctrl_sock.c.obj +[11/1344] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_auth.c.obj +[12/1344] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_socks_proxy.c.obj +[13/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_uri.c.obj +[14/1344] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/xip_impl/mmu_psram_flash.c.obj +[15/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_ws.c.obj +[16/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_txrx.c.obj +[17/1344] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport.c.obj +[18/1344] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/esp32s3/esp_psram_impl_octal.c.obj +[19/1344] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/system_layer/esp_psram.c.obj +[20/1344] Building C object esp-idf/esp_https_ota/CMakeFiles/__idf_esp_https_ota.dir/src/esp_https_ota.c.obj +[21/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali.c.obj +[22/1344] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_internal.c.obj +[23/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_common.c.obj +[24/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_oneshot.c.obj +[25/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali_curve_fitting.c.obj +[26/1344] Linking C static library esp-idf/esp_https_ota/libesp_https_ota.a +[27/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp_adc_cal_common_legacy.c.obj +[28/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_main.c.obj +[29/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/esp32s3/curve_fitting_coefficients.c.obj +[30/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp32s3/esp_adc_cal_legacy.c.obj +[31/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/gdma/adc_dma.c.obj +[32/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_filter.c.obj +[33/1344] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_platform_port.c.obj +[34/1344] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp-tls-crypto/esp_tls_crypto.c.obj +[35/1344] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ssl.c.obj +[36/1344] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_error_capture.c.obj +[37/1344] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_parse.c.obj +[38/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_monitor.c.obj +[39/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_dma_legacy.c.obj +[40/1344] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_continuous.c.obj +[41/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_legacy.c.obj +[42/1344] Linking C static library esp-idf/esp_http_server/libesp_http_server.a +[43/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/sigma_delta_legacy.c.obj +[44/1344] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ws.c.obj +[45/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rtc_temperature_legacy.c.obj +[46/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/touch_sensor_common.c.obj +[47/1344] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls.c.obj +[48/1344] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai.c.obj +[49/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/timer_legacy.c.obj +[50/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/pcnt_legacy.c.obj +[51/1344] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_mbedtls.c.obj +[52/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/twai/twai.c.obj +[53/1344] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_common.c.obj +[54/1344] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/esp_http_client.c.obj +[55/1344] Building C object esp-idf/http_parser/CMakeFiles/__idf_http_parser.dir/http_parser.c.obj +[56/1344] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai_onchip.c.obj +[57/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/i2s_legacy.c.obj +[58/1344] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_slave.c.obj +[59/1344] Building C object esp-idf/esp_driver_tsens/CMakeFiles/__idf_esp_driver_tsens.dir/src/temperature_sensor.c.obj +[60/1344] Building C object esp-idf/esp_driver_sdm/CMakeFiles/__idf_esp_driver_sdm.dir/src/sdm.c.obj +[61/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder.c.obj +[62/1344] Linking C static library esp-idf/esp_http_client/libesp_http_client.a +[63/1344] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_crc.c.obj +[64/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_common.c.obj +[65/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_copy.c.obj +[66/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_bytes.c.obj +[67/1344] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_transaction.c.obj +[68/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/i2c/i2c.c.obj +[69/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/esp32s3/touch_sensor.c.obj +[70/1344] Linking C static library esp-idf/tcp_transport/libtcp_transport.a +[71/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_simple.c.obj +[72/1344] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_host.c.obj +[73/1344] Building C object esp-idf/esp_driver_ledc/CMakeFiles/__idf_esp_driver_ledc.dir/src/ledc.c.obj +[74/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/mcpwm_legacy.c.obj +[75/1344] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_master.c.obj +[76/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_rx.c.obj +[77/1344] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_transaction.c.obj +[78/1344] Linking C static library esp-idf/esp_psram/libesp_psram.a +[79/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sd_pwr_ctrl/sd_pwr_ctrl.c.obj +[80/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_cmd.c.obj +[81/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_common.c.obj +[82/1344] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rmt_legacy.c.obj +[83/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_init.c.obj +[84/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_io.c.obj +[85/1344] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_platform.c.obj +[86/1344] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_std.c.obj +[87/1344] Linking C static library esp-idf/esp_adc/libesp_adc.a +[88/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_sd.c.obj +[89/1344] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_mmc.c.obj +[90/1344] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_tx.c.obj +[91/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cmpr.c.obj +[92/1344] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_tdm.c.obj +[93/1344] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_common.c.obj +[94/1344] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_host.c.obj +[95/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_com.c.obj +[96/1344] Linking C static library esp-idf/esp-tls/libesp-tls.a +[97/1344] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub-entry.S.obj +[98/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_sync.c.obj +[99/1344] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub_xtensa.c.obj +[100/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_fault.c.obj +[101/1344] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub_transport.c.obj +[102/1344] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/xt_debugexception.S.obj +[103/1344] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub.c.obj +[104/1344] Linking C static library esp-idf/http_parser/libhttp_parser.a +[105/1344] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/packet.c.obj +[106/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_gen.c.obj +[107/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_oper.c.obj +[108/1344] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_pdm.c.obj +[109/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/lib_printf.c.obj +[110/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_timer.c.obj +[111/1344] Building C object esp-idf/esp_driver_pcnt/CMakeFiles/__idf_esp_driver_pcnt.dir/src/pulse_cnt.c.obj +[112/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig.c.obj +[113/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default_ap.c.obj +[114/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/mesh_event.c.obj +[115/1344] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cap.c.obj +[116/1344] Linking C static library esp-idf/driver/libdriver.a +[117/1344] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug_diagram.c.obj +[118/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj +[119/1344] Linking C static library esp-idf/esp_driver_twai/libesp_driver_twai.a +[120/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default.c.obj +[121/1344] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/esp32s3/esp_coex_adapter.c.obj +[122/1344] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug.c.obj +[123/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32s3/esp_adapter.c.obj +[124/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/regulatory/esp_wifi_regulatory.c.obj +[125/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/os_xtensa.c.obj +[126/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_netif.c.obj +[127/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ap_config.c.obj +[128/1344] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave.c.obj +[129/1344] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave_hd.c.obj +[130/1344] Linking C static library esp-idf/esp_driver_ledc/libesp_driver_ledc.a +[131/1344] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_common.c.obj +[132/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/eloop.c.obj +[133/1344] Linking C static library esp-idf/esp_driver_i2c/libesp_driver_i2c.a +[134/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/bitfield.c.obj +[135/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_1x.c.obj +[136/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_11.c.obj +[137/1344] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig_ack.c.obj +[138/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/sta_info.c.obj +[139/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth_ie.c.obj +[140/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/dragonfly.c.obj +[141/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/pmksa_cache_auth.c.obj +[142/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/comeback_token.c.obj +[143/1344] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_master.c.obj +[144/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-siv.c.obj +[145/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-kdf.c.obj +[146/1344] Linking C static library esp-idf/esp_driver_sdm/libesp_driver_sdm.a +[147/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/wpa_common.c.obj +[148/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-gcm.c.obj +[149/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_ops.c.obj +[150/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ccmp.c.obj +[151/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tlsprf.c.obj +[152/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-tlsprf.c.obj +[153/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-prf.c.obj +[154/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_group5.c.obj +[155/1344] Linking C static library esp-idf/esp_driver_tsens/libesp_driver_tsens.a +[156/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-prf.c.obj +[157/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-prf.c.obj +[158/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_groups.c.obj +[159/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-tlsprf.c.obj +[160/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ms_funcs.c.obj +[161/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth.c.obj +[162/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_common/eap_wsc_common.c.obj +[163/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tprf.c.obj +[164/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/md4-internal.c.obj +[165/1344] Linking C static library esp-idf/esp_driver_rmt/libesp_driver_rmt.a +[166/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/chap.c.obj +[167/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_common.c.obj +[168/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap_common.c.obj +[169/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls.c.obj +[170/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/ieee802_11_common.c.obj +[171/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_mschapv2.c.obj +[172/1344] Linking C static library esp-idf/esp_driver_sdspi/libesp_driver_sdspi.a +[173/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap.c.obj +[174/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap.c.obj +[175/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/mschapv2.c.obj +[176/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_common.c.obj +[177/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae.c.obj +[178/1344] Linking C static library esp-idf/esp_driver_sdmmc/libesp_driver_sdmmc.a +[179/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/pmksa_cache.c.obj +[180/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/common.c.obj +[181/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa_ie.c.obj +[182/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/base64.c.obj +[183/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/ext_password.c.obj +[184/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/uuid.c.obj +[185/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls_common.c.obj +[186/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_ttls.c.obj +[187/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_pac.c.obj +[188/1344] Linking C static library esp-idf/sdmmc/libsdmmc.a +[189/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpabuf.c.obj +[190/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpa_debug.c.obj +[191/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa2_api_port.c.obj +[192/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/json.c.obj +[193/1344] Linking C static library esp-idf/esp_driver_i2s/libesp_driver_i2s.a +[194/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps.c.obj +[195/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_parse.c.obj +[196/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_process.c.obj +[197/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast.c.obj +[198/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_build.c.obj +[199/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_common.c.obj +[200/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_dev_attr.c.obj +[201/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_common.c.obj +[202/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa_main.c.obj +[203/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae_pk.c.obj +[204/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpas_glue.c.obj +[205/1344] Linking C static library esp-idf/esp_driver_mcpwm/libesp_driver_mcpwm.a +[206/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa.c.obj +[207/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_owe.c.obj +[208/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpsk.c.obj +[209/1344] Linking C static library esp-idf/esp_driver_pcnt/libesp_driver_pcnt.a +[210/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_eap_client.c.obj +[211/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_enrollee.c.obj +[212/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/rc4.c.obj +[213/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa3.c.obj +[214/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-unwrap.c.obj +[215/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-wrap.c.obj +[216/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_hostap.c.obj +[217/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpbkdf2.c.obj +[218/1344] Linking C static library esp-idf/esp_gdbstub/libesp_gdbstub.a +[219/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-ccm.c.obj +[220/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_defaults.c.obj +[221/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_objects.c.obj +[222/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c.obj +[223/1344] Linking C static library esp-idf/esp_driver_spi/libesp_driver_spi.a +[224/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls.c.obj +[225/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wps.c.obj +[226/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_handlers.c.obj +[227/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/des-internal.c.obj +[228/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip_defaults.c.obj +[229/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/tls_mbedtls.c.obj +[230/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj +[231/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c.obj +[232/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj +[233/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj +[234/1344] Linking C static library esp-idf/esp_wifi/libesp_wifi.a +[235/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/err.c.obj +[236/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_sntp.c.obj +[237/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj +[238/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/sntp/sntp.c.obj +[239/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/if_api.c.obj +[240/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netifapi.c.obj +[241/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netdb.c.obj +[242/1344] Linking C static library esp-idf/esp_coex/libesp_coex.a +[243/1344] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-ec.c.obj +[244/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/def.c.obj +[245/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/netbiosns/netbiosns.c.obj +[246/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/sntp/sntp.c.obj +[247/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj +[248/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj +[249/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/dns.c.obj +[250/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj +[251/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/init.c.obj +[252/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ip.c.obj +[253/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/mem.c.obj +[254/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/memp.c.obj +[255/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/stats.c.obj +[256/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/sys.c.obj +[257/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj +[258/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/raw.c.obj +[259/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj +[260/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/netif.c.obj +[261/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/autoip.c.obj +[262/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/icmp.c.obj +[263/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_out.c.obj +[264/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/timeouts.c.obj +[265/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj +[266/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_in.c.obj +[267/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj +[268/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp.c.obj +[269/1344] Linking C static library esp-idf/wpa_supplicant/libwpa_supplicant.a +[270/1344] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj +[271/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj +[272/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/dhcp6.c.obj +[273/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/igmp.c.obj +[274/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj +[275/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/dhcp.c.obj +[276/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/inet6.c.obj +[277/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj +[278/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_frag.c.obj +[279/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_napt.c.obj +[280/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_frag.c.obj +[281/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif.c.obj +[282/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ethip6.c.obj +[283/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_addr.c.obj +[284/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/auth.c.obj +[285/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj +[286/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif_fdb.c.obj +[287/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/slipif.c.obj +[288/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap_ms.c.obj +[289/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ccp.c.obj +[290/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-new.c.obj +[291/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/icmp6.c.obj +[292/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ecp.c.obj +[293/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-md5.c.obj +[294/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/demand.c.obj +[295/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eap.c.obj +[296/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eui64.c.obj +[297/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6.c.obj +[298/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/lcp.c.obj +[299/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/mld6.c.obj +[300/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/fsm.c.obj +[301/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipv6cp.c.obj +[302/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipcp.c.obj +[303/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ppp.c.obj +[304/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/mppe.c.obj +[305/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/multilink.c.obj +[306/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppapi.c.obj +[307/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/magic.c.obj +[308/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppoe.c.obj +[309/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/upap.c.obj +[310/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppcrypt.c.obj +[311/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppol2tp.c.obj +[312/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppos.c.obj +[313/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/utils.c.obj +[314/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/if_index.c.obj +[315/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/vj.c.obj +[316/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/des.c.obj +[317/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/freertos/sys_arch.c.obj +[318/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping_sock.c.obj +[319/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/lwip_default_hooks.c.obj +[320/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/debug/lwip_debug.c.obj +[321/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/sockets_ext.c.obj +[322/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32xx/vfs_lwip.c.obj +[323/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/tcp_isn_default.c.obj +[324/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/esp_ping.c.obj +[325/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping.c.obj +[326/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/acd_dhcp_check.c.obj +[327/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md4.c.obj +[328/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md5.c.obj +[329/1344] Linking C static library esp-idf/esp_netif/libesp_netif.a +[330/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/sha1.c.obj +[331/1344] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_connection_monitor.c.obj +[332/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/arc4.c.obj +[333/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/nd6.c.obj +[334/1344] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/nullfs.c.obj +[335/1344] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/lib_printf.c.obj +[336/1344] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/esp32s3/phy_init_data.c.obj +[337/1344] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_common.c.obj +[338/1344] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj +[339/1344] Building C object esp-idf/esp_vfs_console/CMakeFiles/__idf_esp_vfs_console.dir/vfs_console.c.obj +[340/1344] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_eventfd.c.obj +[341/1344] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag.c.obj +[342/1344] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_vfs.c.obj +[343/1344] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/dhcpserver/dhcpserver.c.obj +[344/1344] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/btbb_init.c.obj +[345/1344] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_semihost.c.obj +[346/1344] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj +[347/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_platform.cpp.obj +[348/1344] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader.c.obj +[349/1344] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs.c.obj +[350/1344] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_aes.c.obj +[351/1344] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_xts_aes.c.obj +[352/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition.cpp.obj +[353/1344] Linking C static library esp-idf/lwip/liblwip.a +[354/1344] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/default_event_loop.c.obj +[355/1344] Linking C static library esp-idf/vfs/libvfs.a +[356/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_lookup.cpp.obj +[357/1344] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event_private.c.obj +[358/1344] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event.c.obj +[359/1344] Linking C static library esp-idf/esp_vfs_console/libesp_vfs_console.a +[360/1344] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_wakeup.c.obj +[361/1344] Linking C static library esp-idf/esp_driver_usb_serial_jtag/libesp_driver_usb_serial_jtag.a +[362/1344] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uhci.c.obj +[363/1344] Linking C static library esp-idf/esp_phy/libesp_phy.a +[364/1344] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer.c.obj +[365/1344] Building C object esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj +[366/1344] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_vfs.c.obj +[367/1344] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer_common.c.obj +[368/1344] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_init.c.obj +[369/1344] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj +[370/1344] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj +[371/1344] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj +[372/1344] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj +[373/1344] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_exception_stubs.cpp.obj +[374/1344] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_init.cpp.obj +[375/1344] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj +[376/1344] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart.c.obj +[377/1344] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj +[378/1344] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_cond_var.c.obj +[379/1344] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_local_storage.c.obj +[380/1344] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_rwlock.c.obj +[381/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/init.c.obj +[382/1344] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_semaphore.c.obj +[383/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/abort.c.obj +[384/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/assert.c.obj +[385/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/heap.c.obj +[386/1344] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_guards.cpp.obj +[387/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/poll.c.obj +[388/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/locks.c.obj +[389/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/pthread.c.obj +[390/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/random.c.obj +[391/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/getentropy.c.obj +[392/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/termios.c.obj +[393/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/sysconf.c.obj +[394/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/realpath.c.obj +[395/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/scandir.c.obj +[396/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/time.c.obj +[397/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/syscalls.c.obj +[398/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/esp_time_impl.c.obj +[399/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_syscalls.c.obj +[400/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/flockfile.c.obj +[401/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_init.c.obj +[402/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/xtensa/stdatomic_s32c1i.c.obj +[403/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/newlib_init.c.obj +[404/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj +[405/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/app_startup.c.obj +[406/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj +[407/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj +[408/1344] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/stdatomic.c.obj +[409/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj +[410/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/event_groups.c.obj +[411/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/timers.c.obj +[412/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/stream_buffer.c.obj +[413/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj +[414/1344] Building ASM object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/portasm.S.obj +[415/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_init.c.obj +[416/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/port.c.obj +[417/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_item_hash_list.cpp.obj +[418/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_overlay_os_hook.c.obj +[419/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_pagemanager.cpp.obj +[420/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/freertos_compatibility.c.obj +[421/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_encrypted_partition.cpp.obj +[422/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_types.cpp.obj +[423/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_locked.cpp.obj +[424/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions_event_groups.c.obj +[425/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions.c.obj +[426/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[427/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_simple.cpp.obj +[428/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[429/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[430/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[431/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj +[432/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_ctrl_os.c.obj +[433/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mac_addr.c.obj +[434/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_gpio_reserve.c.obj +[435/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/revision.c.obj +[436/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj +[437/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj +[438/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj +[439/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj +[440/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj +[441/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_clk_tree.c.obj +[442/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/io_mux.c.obj +[443/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma_link.c.obj +[444/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sar_periph_ctrl_common.c.obj +[445/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_dma_utils.c.obj +[446/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_utils.c.obj +[447/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_clk_tree_common.c.obj +[448/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_share_hw_ctrl.c.obj +[449/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_api.cpp.obj +[450/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_mspi.c.obj +[451/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_usb.c.obj +[452/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/adc_share_hw_ctrl.c.obj +[453/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_manager.cpp.obj +[454/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modem.c.obj +[455/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_cxx_api.cpp.obj +[456/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_console.c.obj +[457/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_event.c.obj +[458/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/systimer.c.obj +[459/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_bus_lock.c.obj +[460/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_async_memcpy.c.obj +[461/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/deprecated/gdma_legacy.c.obj +[462/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/async_memcpy_gdma.c.obj +[463/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_page.cpp.obj +[464/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_gpio.c.obj +[465/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_wake_stub.c.obj +[466/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/mspi_timing_tuning.c.obj +[467/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/power_supply/brownout.c.obj +[468/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[469/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[470/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[471/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[472/1344] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj +[473/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clock_output.c.obj +[474/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[475/1344] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_storage.cpp.obj +[476/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/sar_periph_ctrl.c.obj +[477/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_config.c.obj +[478/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[479/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_memprot_conv.c.obj +[480/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj +[481/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[482/1344] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_lock.c.obj +[483/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[484/1344] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_hmac.c.obj +[485/1344] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/init.c.obj +[486/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[487/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[488/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[489/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c.obj +[490/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/lowpower/port/esp32s3/sleep_cpu.c.obj +[491/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[492/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[493/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[494/1344] Linking C static library esp-idf/nvs_flash/libnvs_flash.a +[495/1344] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_periph_clk.c.obj +[496/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[497/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[498/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma.c.obj +[499/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[500/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[501/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[502/1344] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_ds.c.obj +[503/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[504/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[505/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[506/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[507/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[508/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[509/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[510/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[511/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[512/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[513/1344] Linking C static library esp-idf/esp_event/libesp_event.a +[514/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[515/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[516/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[517/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[518/1344] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[519/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/esp32s3/memory_layout.c.obj +[520/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_timestamp.c.obj +[521/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap_poisoning.c.obj +[522/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_lock.c.obj +[523/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj +[524/1344] Linking C static library esp-idf/esp_driver_uart/libesp_driver_uart.a +[525/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[526/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/memory_layout_utils.c.obj +[527/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_init.c.obj +[528/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[529/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[530/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj +[531/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj +[532/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[533/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[534/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[535/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/log_level.c.obj +[536/1344] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/tlsf/tlsf.c.obj +[537/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_write.c.obj +[538/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/util.c.obj +[539/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/linked_list/log_linked_list.c.obj +[540/1344] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_memprot.c.obj +[541/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[542/1344] Linking C static library esp-idf/esp_ringbuf/libesp_ringbuf.a +[543/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[544/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/cache/log_binary_heap.c.obj +[545/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[546/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/color_hal.c.obj +[547/1344] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/tag_log_level.c.obj +[548/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[549/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[550/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_encrypt_hal_iram.c.obj +[551/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj +[552/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal_iram.c.obj +[553/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gpio_hal.c.obj +[554/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[555/1344] Linking C static library esp-idf/esp_driver_gptimer/libesp_driver_gptimer.a +[556/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal.c.obj +[557/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/timer_hal.c.obj +[558/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal.c.obj +[559/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/clk_tree_hal.c.obj +[560/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rtc_io_hal.c.obj +[561/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal.c.obj +[562/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal_iram.c.obj +[563/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal_iram.c.obj +[564/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rmt_hal.c.obj +[565/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/pcnt_hal.c.obj +[566/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uhci_hal.c.obj +[567/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_top.c.obj +[568/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal.c.obj +[569/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mcpwm_hal.c.obj +[570/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj +[571/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdm_hal.c.obj +[572/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdmmc_hal.c.obj +[573/1344] Linking C static library esp-idf/esp_timer/libesp_timer.a +[574/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal_common.c.obj +[575/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/twai_hal_v1.c.obj +[576/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_ahb_v1.c.obj +[577/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sha_hal.c.obj +[578/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_oneshot_hal.c.obj +[579/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/lcd_hal.c.obj +[580/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpi_hal.c.obj +[581/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj +[582/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/aes_hal.c.obj +[583/1344] Linking C static library esp-idf/cxx/libcxx.a +[584/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal_iram.c.obj +[585/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal.c.obj +[586/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hmac_hal.c.obj +[587/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal.c.obj +[588/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_serial_jtag_hal.c.obj +[589/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ds_hal.c.obj +[590/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal.c.obj +[591/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hd_hal.c.obj +[592/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj +[593/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cam_hal.c.obj +[594/1344] Linking C static library esp-idf/pthread/libpthread.a +[595/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[596/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_wrap_hal.c.obj +[597/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/rtc_cntl_hal.c.obj +[598/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2s_hal.c.obj +[599/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal_iram.c.obj +[600/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sensor_hal.c.obj +[601/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sens_hal.c.obj +[602/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/xt_wdt_hal.c.obj +[603/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[604/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[605/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[606/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/touch_sensor_hal.c.obj +[607/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[608/1344] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[609/1344] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[610/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[611/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[612/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[613/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[614/1344] Linking C static library esp-idf/newlib/libnewlib.a +[615/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system_console.c.obj +[616/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[617/1344] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_dwc_hal.c.obj +[618/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj +[619/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_ipc.c.obj +[620/1344] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[621/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj +[622/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup.c.obj +[623/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/stack_check.c.obj +[624/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj +[625/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/system_time.c.obj +[626/1344] Linking C static library esp-idf/freertos/libfreertos.a +[627/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj +[628/1344] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_handler.S.obj +[629/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj +[630/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/xt_wdt.c.obj +[631/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/panic.c.obj +[632/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_port.c.obj +[633/1344] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_routines.S.obj +[634/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/image_process.c.obj +[635/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj +[636/1344] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_handler_asm.S.obj +[637/1344] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack_asm.S.obj +[638/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_ipc_isr.c.obj +[639/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj +[640/1344] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers_asm.S.obj +[641/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack.c.obj +[642/1344] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[643/1344] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/highint_hdl.S.obj +[644/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_stubs.c.obj +[645/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/trax.c.obj +[646/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup_funcs.c.obj +[647/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj +[648/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj +[649/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_arch.c.obj +[650/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/reset_reason.c.obj +[651/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj +[652/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers.c.obj +[653/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_drivers.c.obj +[654/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/apb_backup_dma.c.obj +[655/1344] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[656/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/system_internal.c.obj +[657/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_issi.c.obj +[658/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_gd.c.obj +[659/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_boya.c.obj +[660/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/cache_err_int.c.obj +[661/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_winbond.c.obj +[662/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_hpm_enable.c.obj +[663/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp32s3/spi_flash_oct_flash_init.c.obj +[664/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_th.c.obj +[665/1344] Linking C static library esp-idf/esp_security/libesp_security.a +[666/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic.c.obj +[667/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic_opi.c.obj +[668/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[669/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/memspi_host_driver.c.obj +[670/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj +[671/1344] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/port/esp32s3/ext_mem_layout.c.obj +[672/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj +[673/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj +[674/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj +[675/1344] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/clk.c.obj +[676/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj +[677/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj +[678/1344] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/heap_align_hw.c.obj +[679/1344] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_utils.c.obj +[680/1344] Linking C static library esp-idf/soc/libsoc.a +[681/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[682/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[683/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[684/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[685/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[686/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[687/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[688/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[689/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_generic.c.obj +[690/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_spi_init.c.obj +[691/1344] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_msync.c.obj +[692/1344] Linking C static library esp-idf/heap/libheap.a +[693/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[694/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[695/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[696/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/secure_boot_secure_features.c.obj +[697/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[698/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[699/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[700/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[701/1344] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj +[702/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[703/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[704/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[705/1344] Linking C static library esp-idf/log/liblog.a +[706/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[707/1344] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[708/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[709/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/debug.c.obj +[710/1344] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_api.c.obj +[711/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[712/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_startup.c.obj +[713/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_reader.c.obj +[714/1344] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_app_desc.c.obj +[715/1344] Building C object esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj +[716/1344] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[717/1344] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition_target.c.obj +[718/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[719/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_trace.c.obj +[720/1344] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition.c.obj +[721/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_server.c.obj +[722/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_keys.c.obj +[723/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_client.c.obj +[724/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_debug_helpers_generated.c.obj +[725/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ciphersuites.c.obj +[726/1344] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[727/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_generic.c.obj +[728/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cookie.c.obj +[729/1344] Linking C static library esp-idf/hal/libhal.a +[730/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cache.c.obj +[731/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/mbedtls_debug.c.obj +[732/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_platform_time.c.obj +[733/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ticket.c.obj +[734/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_client.c.obj +[735/1344] Linking C static library esp-idf/esp_rom/libesp_rom.a +[736/1344] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_ops.c.obj +[737/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/pkcs7.c.obj +[738/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_create.c.obj +[739/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write.c.obj +[740/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_csr.c.obj +[741/1344] Linking C static library esp-idf/esp_common/libesp_common.a +[742/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crl.c.obj +[743/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_csr.c.obj +[744/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesni.c.obj +[745/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesce.c.obj +[746/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_crt.c.obj +[747/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aes.c.obj +[748/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/net_sockets.c.obj +[749/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_client.c.obj +[750/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod.c.obj +[751/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1write.c.obj +[752/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod_raw.c.obj +[753/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aria.c.obj +[754/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/block_cipher.c.obj +[755/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1parse.c.obj +[756/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/camellia.c.obj +[757/1344] Linking C static library esp-idf/esp_system/libesp_system.a +[758/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_server.c.obj +[759/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509.c.obj +[760/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/base64.c.obj +[761/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chachapoly.c.obj +[762/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chacha20.c.obj +[763/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_msg.c.obj +[764/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/des.c.obj +[765/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/dhm.c.obj +[766/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/constant_time.c.obj +[767/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecjpake.c.obj +[768/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ccm.c.obj +[769/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher_wrap.c.obj +[770/1344] Linking C static library esp-idf/spi_flash/libspi_flash.a +[771/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cmac.c.obj +[772/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ctr_drbg.c.obj +[773/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves_new.c.obj +[774/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdh.c.obj +[775/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdsa.c.obj +[776/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_core.c.obj +[777/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy_poll.c.obj +[778/1344] Linking C static library esp-idf/esp_mm/libesp_mm.a +[779/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy.c.obj +[780/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hkdf.c.obj +[781/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/error.c.obj +[782/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hmac_drbg.c.obj +[783/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md5.c.obj +[784/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/memory_buffer_alloc.c.obj +[785/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lmots.c.obj +[786/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/nist_kw.c.obj +[787/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lms.c.obj +[788/1344] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[789/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/padlock.c.obj +[790/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md.c.obj +[791/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher.c.obj +[792/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_ecc.c.obj +[793/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pem.c.obj +[794/1344] Linking C static library esp-idf/efuse/libefuse.a +[795/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum.c.obj +[796/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs12.c.obj +[797/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform.c.obj +[798/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crt.c.obj +[799/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves.c.obj +[800/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform_util.c.obj +[801/1344] Linking C static library esp-idf/esp_partition/libesp_partition.a +[802/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/poly1305.c.obj +[803/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/oid.c.obj +[804/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs5.c.obj +[805/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk.c.obj +[806/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/gcm.c.obj +[807/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_wrap.c.obj +[808/1344] Linking C static library esp-idf/app_update/libapp_update.a +[809/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_client.c.obj +[810/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkwrite.c.obj +[811/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_driver_wrappers_no_static.c.obj +[812/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp.c.obj +[813/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ffdh.c.obj +[814/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_pake.c.obj +[815/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_se.c.obj +[816/1344] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[817/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_mac.c.obj +[818/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_cipher.c.obj +[819/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_hash.c.obj +[820/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls.c.obj +[821/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_storage.c.obj +[822/1344] Linking C static library esp-idf/esp_app_format/libesp_app_format.a +[823/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ripemd160.c.obj +[824/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_its_file.c.obj +[825/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkparse.c.obj +[826/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_aead.c.obj +[827/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_rsa.c.obj +[828/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha1.c.obj +[829/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_util.c.obj +[830/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ecp.c.obj +[831/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa_alt_helpers.c.obj +[832/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha3.c.obj +[833/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/threading.c.obj +[834/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/timing.c.obj +[835/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha512.c.obj +[836/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version.c.obj +[837/1344] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedtls.a +[838/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha256.c.obj +[839/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version_features.c.obj +[840/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha_gdma_impl.c.obj +[841/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_slot_management.c.obj +[842/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_timing.c.obj +[843/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_gdma_impl.c.obj +[844/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_mem.c.obj +[845/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_xts.c.obj +[846/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hardware.c.obj +[847/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_common.c.obj +[848/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/esp_sha.c.obj +[849/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c.obj +[850/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hmac_pbkdf2.c.obj +[851/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c.obj +[852/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/bignum_alt.c.obj +[853/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_dec_alt.c.obj +[854/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/md/esp_md.c.obj +[855/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha256.c.obj +[856/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_ds_common.c.obj +[857/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha1.c.obj +[858/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/esp_bignum.c.obj +[859/1344] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m/p256-m.c.obj +[860/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/sha.c.obj +[861/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha512.c.obj +[862/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c.obj +[863/1344] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m_driver_entrypoints.c.obj +[864/1344] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/x25519.c.obj +[865/1344] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedx509.a +[866/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_dma_core.c.obj +[867/1344] Creating directories for 'bootloader' +[868/1344] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/everest.c.obj +[869/1344] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/Hacl_Curve25519_joined.c.obj +[870/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_gcm.c.obj +[871/1344] No download step for 'bootloader' +[872/1344] No update step for 'bootloader' +[873/1344] No patch step for 'bootloader' +[874/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa.c.obj +[875/1344] Minifying + gzipping web resources +Minifying web resources in /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/ts_webui/web_optimized... + JS js/terminal.js: 31,108 -> 20,066 (35.5% saved) + JS js/router.js: 6,414 -> 3,839 (40.1% saved) + JS js/dragSort.js: 11,460 -> 7,603 (33.7% saved) + JS js/api.js: 36,638 -> 24,339 (33.6% saved) + JS js/i18n.js: 7,208 -> 4,320 (40.1% saved) + JS js/app.js: 1,129,944 -> 840,829 (25.6% saved) + JS js/lang/en-US.js: 178,439 -> 143,161 (19.8% saved) + JS js/lang/zh-CN.js: 172,046 -> 137,314 (20.2% saved) + CSS css/style.css: 179,071 -> 129,275 (27.8% saved) + CSS fonts/remixicon.css: 5,940 -> 4,860 (18.2% saved) + + Total saved: 442,662 bytes (432.3 KB) + +Gzipping web resources in /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/ts_webui/web_optimized... + GZ js/terminal.js: 20,066 -> 5,565 (72.3% smaller) + GZ js/router.js: 3,839 -> 1,340 (65.1% smaller) + GZ js/dragSort.js: 7,603 -> 1,869 (75.4% smaller) + GZ js/api.js: 24,339 -> 6,163 (74.7% smaller) + GZ js/i18n.js: 4,320 -> 1,460 (66.2% smaller) + GZ js/app.js: 840,829 -> 167,747 (80.0% smaller) + GZ js/lang/en-US.js: 143,161 -> 43,017 (70.0% smaller) + GZ js/lang/zh-CN.js: 137,314 -> 45,286 (67.0% smaller) + GZ vendor/xterm/fit.min.js: 1,789 -> 822 (54.1% smaller) + GZ vendor/xterm/xterm.min.js: 283,670 -> 65,684 (76.8% smaller) + GZ css/style.css: 129,275 -> 20,658 (84.0% smaller) + GZ fonts/remixicon.css: 4,860 -> 1,263 (74.0% smaller) + GZ vendor/xterm/xterm.css: 5,383 -> 2,037 (62.2% smaller) + GZ index.html: 26,676 -> 7,261 (72.8% smaller) + + Gzipped 14 files: 1,633,124 -> 370,172 (77.3% overall) +Done. +[876/1344] cd /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ssh-stack-diagnostic/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[877/1344] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto.c.obj +[878/1344] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a +[879/1344] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/p256-m/libp256m.a +[880/1344] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/everest/libeverest.a +[881/1344] Generating x509_crt_bundle +[882/1344] Generating ../../x509_crt_bundle.S +[883/1344] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[884/1344] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr_asm.S.obj +[885/1344] Building ASM object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/__/__/x509_crt_bundle.S.obj +[886/1344] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_context.S.obj +[887/1344] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[888/1344] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj +[889/1344] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_trace.c.obj +[890/1344] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_glitch_filter_ops.c.obj +[891/1344] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr.c.obj +[892/1344] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_vectors.S.obj +[893/1344] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_pin_glitch_filter.c.obj +[894/1344] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj +[895/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/crc32.cpp.obj +[896/1344] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/dedic_gpio.c.obj +[897/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/Partition.cpp.obj +[898/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/SPI_Flash.cpp.obj +[899/1344] Building C object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/esp_crt_bundle/esp_crt_bundle.c.obj +[900/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Safe.cpp.obj +[901/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Perf.cpp.obj +[902/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/port/freertos/ffsystem.c.obj +[903/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/wear_levelling.cpp.obj +[904/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_rawflash.c.obj +[905/1344] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/rtc_io.c.obj +[906/1344] Linking C static library esp-idf/mbedtls/libmbedtls.a +[907/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio.c.obj +[908/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_wl.c.obj +[909/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ffunicode.c.obj +[910/1344] Linking C static library esp-idf/esp_pm/libesp_pm.a +[911/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_cache.c.obj +[912/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs_api.c.obj +[913/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_sdmmc.c.obj +[914/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_spiflash.c.obj +[915/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/split_argv.c.obj +[916/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_internal.c.obj +[917/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_common.c.obj +[918/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_check.c.obj +[919/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/commands.c.obj +[920/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_gc.c.obj +[921/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_sdmmc.c.obj +[922/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dbl.c.obj +[923/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_chip.c.obj +[924/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/linenoise/linenoise.c.obj +[925/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_cmd.c.obj +[926/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_end.c.obj +[927/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dstr.c.obj +[928/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_file.c.obj +[929/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_lit.c.obj +[930/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_date.c.obj +[931/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rem.c.obj +[932/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_hashtable.c.obj +[933/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_str.c.obj +[934/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_int.c.obj +[935/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_utils.c.obj +[936/1344] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Flash.cpp.obj +[937/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_hydrogen.c.obj +[938/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/esp_spiffs.c.obj +[939/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat.c.obj +[940/1344] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio.c.obj +[941/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rex.c.obj +[942/1344] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth_netif_glue.c.obj +[943/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/compress.c.obj +[944/1344] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_phy_w5500.c.obj +[945/1344] Linking C static library esp-idf/esp_driver_gpio/libesp_driver_gpio.a +[946/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/adler32.c.obj +[947/1344] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/argtable3.c.obj +[948/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/crc32.c.obj +[949/1344] Building C object esp-idf/ts_event/CMakeFiles/__idf_ts_event.dir/src/ts_event.c.obj +[950/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzclose.c.obj +[951/1344] Linking C static library esp-idf/xtensa/libxtensa.a +[952/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzlib.c.obj +[953/1344] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON_Utils.c.obj +[954/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzwrite.c.obj +[955/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzread.c.obj +[956/1344] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_nucleus.c.obj +[957/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/infback.c.obj +[958/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inffast.c.obj +[959/1344] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/phy/esp_eth_phy_802_3.c.obj +[960/1344] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth.c.obj +[961/1344] Linking C static library esp-idf/wear_levelling/libwear_levelling.a +[962/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/uncompr.c.obj +[963/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inftrees.c.obj +[964/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/zutil.c.obj +[965/1344] Linking C static library esp-idf/spiffs/libspiffs.a +[966/1344] Linking C static library esp-idf/ts_event/libts_event.a +[967/1344] Linking C static library esp-idf/console/libconsole.a +[968/1344] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_api.c.obj +[969/1344] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_encoder.c.obj +[970/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/deflate.c.obj +[971/1344] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_dev.c.obj +[972/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/example.c.obj +[973/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/trees.c.obj +[974/1344] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_mac_w5500.c.obj +[975/1344] Building C object esp-idf/espressif__esp_jpeg/CMakeFiles/__idf_espressif__esp_jpeg.dir/jpeg_decoder.c.obj +[976/1344] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_spi_dev.c.obj +[977/1344] Linking C static library esp-idf/esp_eth/libesp_eth.a +[978/1344] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inflate.c.obj +[979/1344] Building C object esp-idf/ts_log/CMakeFiles/__idf_ts_log.dir/src/ts_log.c.obj +[980/1344] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON.c.obj +[981/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrio.c.obj +[982/1344] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ff.c.obj +[983/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngmem.c.obj +[984/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngerror.c.obj +[985/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngpread.c.obj +[986/1344] Building C object esp-idf/esp_https_server/CMakeFiles/__idf_esp_https_server.dir/src/https_server.c.obj +[987/1344] Linking C static library esp-idf/json/libjson.a +[988/1344] Linking C static library esp-idf/espressif__zlib/libespressif__zlib.a +[989/1344] Linking C static library esp-idf/fatfs/libfatfs.a +[990/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwio.c.obj +[991/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtrans.c.obj +[992/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwtran.c.obj +[993/1344] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_mem_caps.c.obj +[994/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngget.c.obj +[995/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtest.c.obj +[996/1344] Building C object esp-idf/ts_jsonpath/CMakeFiles/__idf_ts_jsonpath.dir/src/ts_jsonpath.c.obj +[997/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngset.c.obj +[998/1344] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_networking_lwip.c.obj +[999/1344] Building C object esp-idf/espressif__esp_websocket_client/CMakeFiles/__idf_espressif__esp_websocket_client.dir/esp_websocket_client.c.obj +[1000/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwrite.c.obj +[1001/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/png.c.obj +[1002/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent_win.c.obj +[1003/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent.c.obj +[1004/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwutil.c.obj +[1005/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/blowfish.c.obj +[1006/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/bcrypt_pbkdf.c.obj +[1007/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/crypt.c.obj +[1008/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/comp.c.obj +[1009/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/global.c.obj +[1010/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/keepalive.c.obj +[1011/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngread.c.obj +[1012/1344] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_console.c.obj +[1013/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/libgcrypt.c.obj +[1014/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/hostkey.c.obj +[1015/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/openssl.c.obj +[1016/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrutil.c.obj +[1017/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mac.c.obj +[1018/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/os400qc3.c.obj +[1019/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/knownhost.c.obj +[1020/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/misc.c.obj +[1021/1344] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrtran.c.obj +[1022/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/publickey.c.obj +[1023/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/packet.c.obj +[1024/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mbedtls.c.obj +[1025/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/channel.c.obj +[1026/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/scp.c.obj +[1027/1344] Linking C static library esp-idf/ts_log/libts_log.a +[1028/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/transport.c.obj +[1029/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/version.c.obj +[1030/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth_kbd_packet.c.obj +[1031/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/pem.c.obj +[1032/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/wincng.c.obj +[1033/1344] Linking C static library esp-idf/esp_https_server/libesp_https_server.a +[1034/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/session.c.obj +[1035/1344] Building C object esp-idf/ts_mempool/CMakeFiles/__idf_ts_mempool.dir/src/ts_mempool.c.obj +[1036/1344] Linking C static library esp-idf/espressif__esp_websocket_client/libespressif__esp_websocket_client.a +[1037/1344] Linking C static library esp-idf/espressif__esp_jpeg/libespressif__esp_jpeg.a +[1038/1344] Linking C static library esp-idf/espressif__led_strip/libespressif__led_strip.a +[1039/1344] Linking C static library esp-idf/ts_jsonpath/libts_jsonpath.a +[1040/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/kex.c.obj +[1041/1344] Linking C static library esp-idf/espressif__libpng/libespressif__libpng.a +[1042/1344] Building C object esp-idf/ts_service/CMakeFiles/__idf_ts_service.dir/src/ts_service.c.obj +[1043/1344] Linking C static library esp-idf/ts_mempool/libts_mempool.a +[1044/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_json.c.obj +[1045/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_nvs.c.obj +[1046/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_schemas.c.obj +[1047/1344] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert_time.c.obj +[1048/1344] Linking C static library esp-idf/ts_service/libts_service.a +[1049/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_meta.c.obj +[1050/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_security.c.obj +[1051/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_file.c.obj +[1052/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config.c.obj +[1053/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_auth.c.obj +[1054/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth.c.obj +[1055/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_client.c.obj +[1056/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_scp.c.obj +[1057/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_known_hosts.c.obj +[1058/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_sftp.c.obj +[1059/1344] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_module.c.obj +[1060/1344] Building C object esp-idf/ts_config_pack/CMakeFiles/__idf_ts_config_pack.dir/src/ts_config_pack.c.obj +[1061/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_probe.c.obj +[1062/1344] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/sftp.c.obj +[1063/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_log_watch.c.obj +[1064/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_port_forward.c.obj +[1065/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_shell.c.obj +[1066/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_crypto.c.obj +[1067/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_variable.c.obj +[1068/1344] Linking C static library esp-idf/ch405labs_esp_libssh2/libch405labs_esp_libssh2.a +[1069/1344] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert.c.obj +[1070/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_hosts_config.c.obj +[1071/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_keystore.c.obj +[1072/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_service.c.obj +[1073/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_automation.c.obj +[1074/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_codec.c.obj +[1075/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_compat.c.obj +[1076/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_store.c.obj +[1077/1344] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_commands_config.c.obj +[1078/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_cache.c.obj +[1079/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_runner.c.obj +[1080/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_freertos.c.obj +[1081/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_memory.c.obj +[1082/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_port_esp32.c.obj +[1083/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/port/esp/unity_utils_memory_esp.c.obj +[1084/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/constants.pb-c.c.obj +[1085/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/session.pb-c.c.obj +[1086/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/common/protocomm.c.obj +[1087/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec1.pb-c.c.obj +[1088/1344] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity/src/unity.c.obj +[1089/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec0.pb-c.c.obj +[1090/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_console.c.obj +[1091/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_httpd.c.obj +[1092/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec2.pb-c.c.obj +[1093/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security0.c.obj +[1094/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp_mpi.c.obj +[1095/1344] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/host_file_io.c.obj +[1096/1344] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace_util.c.obj +[1097/1344] Building C object esp-idf/cmock/CMakeFiles/__idf_cmock.dir/CMock/src/cmock.c.obj +[1098/1344] Linking C static library esp-idf/unity/libunity.a +[1099/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp.c.obj +[1100/1344] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/port/port_uart.c.obj +[1101/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security1.c.obj +[1102/1344] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace.c.obj +[1103/1344] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp_share_ctrl.c.obj +[1104/1344] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security2.c.obj +[1105/1344] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/esp_cam_ctlr.c.obj +[1106/1344] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_gdma.c.obj +[1107/1344] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidd.c.obj +[1108/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_io.c.obj +[1109/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_common.c.obj +[1110/1344] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hid_common.c.obj +[1111/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ssd1306.c.obj +[1112/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_nt35510.c.obj +[1113/1344] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidh.c.obj +[1114/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ops.c.obj +[1115/1344] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/hw_ver2/touch_version_specific.c.obj +[1116/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_st7789.c.obj +[1117/1344] Building C object esp-idf/protobuf-c/CMakeFiles/__idf_protobuf-c.dir/protobuf-c/protobuf-c/protobuf-c.c.obj +[1118/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v2.c.obj +[1119/1344] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns.c.obj +[1120/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v1.c.obj +[1121/1344] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/common/touch_sens_common.c.obj +[1122/1344] Linking C static library esp-idf/protobuf-c/libprotobuf-c.a +[1123/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_init.c.obj +[1124/1344] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_cam.c.obj +[1125/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_engine.c.obj +[1126/1344] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/proto-c/esp_local_ctrl.pb-c.c.obj +[1127/1344] Linking C static library esp-idf/espressif__mdns/libespressif__mdns.a +[1128/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/spi/esp_lcd_panel_io_spi.c.obj +[1129/1344] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_handler.c.obj +[1130/1344] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_transport_httpd.c.obj +[1131/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_common.c.obj +[1132/1344] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl.c.obj +[1133/1344] Linking C static library esp-idf/protocomm/libprotocomm.a +[1134/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_sha.c.obj +[1135/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_uart.c.obj +[1136/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_crc.c.obj +[1137/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_binary.c.obj +[1138/1344] Linking C static library esp-idf/ts_config/libts_config.a +[1139/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_elf.c.obj +[1140/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_flash.c.obj +[1141/1344] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/port/xtensa/core_dump_port.c.obj +[1142/1344] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_masks.c.obj +[1143/1344] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_access.c.obj +[1144/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i80/esp_lcd_panel_io_i80.c.obj +[1145/1344] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/platform_esp32_idf.c.obj +[1146/1344] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_apis.c.obj +[1147/1344] Linking C static library esp-idf/ts_config_pack/libts_config_pack.a +[1148/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_source_manager.c.obj +[1149/1344] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_action_manager.c.obj +[1150/1344] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_msg.c.obj +[1151/1344] Building C object esp-idf/nvs_sec_provider/CMakeFiles/__idf_nvs_sec_provider.dir/nvs_sec_provider.c.obj +[1152/1344] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_outbox.c.obj +[1153/1344] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_mqueue.c.obj +[1154/1344] Linking C static library esp-idf/ts_cert/libts_cert.a +[1155/1344] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/rgb/esp_lcd_panel_rgb.c.obj +[1156/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_private.c.obj +[1157/1344] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_button.c.obj +[1158/1344] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_utils.c.obj +[1159/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_helpers.c.obj +[1160/1344] Linking C static library esp-idf/ts_security/libts_security.a +[1161/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hub.c.obj +[1162/1344] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_matrix.c.obj +[1163/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_config.c.obj +[1164/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_scan.c.obj +[1165/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_ctrl.c.obj +[1166/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/enum.c.obj +[1167/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_phy.c.obj +[1168/1344] Linking C static library esp-idf/ts_automation/libts_automation.a +[1169/1344] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_element.c.obj +[1170/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/handlers.c.obj +[1171/1344] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_slider.c.obj +[1172/1344] Generating ../../lpmu-agx-network-setup.tar.gz.S +[1173/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_scan.pb-c.c.obj +[1174/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_console.c.obj +[1175/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_constants.pb-c.c.obj +[1176/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_config.pb-c.c.obj +[1177/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_host.c.obj +[1178/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_ctrl.pb-c.c.obj +[1179/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_softap.c.obj +[1180/1344] Linking C static library esp-idf/cmock/libcmock.a +[1181/1344] Linking C static library esp-idf/app_trace/libapp_trace.a +[1182/1344] Linking C static library esp-idf/esp_driver_cam/libesp_driver_cam.a +[1183/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usbh.c.obj +[1184/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api.c.obj +[1185/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config.c.obj +[1186/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_fan.c.obj +[1187/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_service.c.obj +[1188/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_power.c.obj +[1189/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_network.c.obj +[1190/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_temp.c.obj +[1191/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config_pack.c.obj +[1192/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_storage.c.obj +[1193/1344] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hcd_dwc.c.obj +[1194/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_monitor.c.obj +[1195/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_gpio.c.obj +[1196/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_system.c.obj +[1197/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_nat.c.obj +[1198/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_dhcp.c.obj +[1199/1344] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/manager.c.obj +[1200/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_hosts.c.obj +[1201/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_device.c.obj +[1202/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_led.c.obj +[1203/1344] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/mqtt_client.c.obj +[1204/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_key.c.obj +[1205/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_wifi.c.obj +[1206/1344] Building ASM object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/__/__/lpmu-agx-network-setup.tar.gz.S.obj +[1207/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_lpmu_access.c.obj +[1208/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_log.c.obj +[1209/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_auth.c.obj +[1210/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_sftp.c.obj +[1211/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_time.c.obj +[1212/1344] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_api.c.obj +[1213/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ui.c.obj +[1214/1344] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui.c.obj +[1215/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_cert.c.obj +[1216/1344] Performing configure step for 'bootloader' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-ssh-stack-diagnostic/sdkconfig +-- Compiler supported targets: xtensa-esp-elf +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Bootloader project name: "bootloader" version: 1 +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.rom.ld +-- Components: bootloader bootloader_support efuse esp_app_format esp_bootloader_format esp_common esp_hw_support esp_rom esp_security esp_system esptool_py freertos hal log main micro-ecc newlib partition_table soc spi_flash xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/components/micro-ecc /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +-- Configuring done (4.5s) +-- Generating done (0.2s) +-- Build files have been written to: /tmp/tianshan-ssh-stack-diagnostic/build/bootloader +[1217/1344] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https.c.obj +[1218/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_i18n.c.obj +[1219/1344] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_auth.c.obj +[1220/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_args.c.obj +[1221/1344] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_api.c.obj +[1222/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ota.c.obj +[1223/1344] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_operation.c.obj +[1224/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console.c.obj +[1225/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_script.c.obj +[1226/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_builtin.c.obj +[1227/1344] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[1228/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/linenoise/linenoise.c.obj +[1229/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_monitor.c.obj +[1230/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_auto.c.obj +[1231/1344] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_transport.c.obj +[1232/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fan.c.obj +[1233/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_device.c.obj +[1234/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_hosts.c.obj +[1235/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_gpio.c.obj +[1236/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_config.c.obj +[1237/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_nat.c.obj +[1238/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fs.c.obj +[1239/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_dhcp.c.obj +[1240/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ssh.c.obj +[1241/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_key.c.obj +[1242/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_register.c.obj +[1243/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_net.c.obj +[1244/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ota.c.obj +[1245/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_pki.c.obj +[1246/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_service.c.obj +[1247/1344] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[1248/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_power.c.obj +[1249/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_sftp.c.obj +[1250/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_voltprot.c.obj +[1251/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota.c.obj +[1252/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_version.c.obj +[1253/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_system.c.obj +[1254/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_rollback.c.obj +[1255/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_temp.c.obj +[1256/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_sdcard.c.obj +[1257/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_wifi.c.obj +[1258/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_storage.c.obj +[1259/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ssh.c.obj +[1260/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_recovery.c.obj +[1261/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_https.c.obj +[1262/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net.c.obj +[1263/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_wifi.c.obj +[1264/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_www.c.obj +[1265/1344] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_download.c.obj +[1266/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_nat.c.obj +[1267/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_eth.c.obj +[1268/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_driver.c.obj +[1269/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_http_server.c.obj +[1270/1344] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_led.c.obj +[1271/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_time_sync.c.obj +[1272/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led.c.obj +[1273/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_layer.c.obj +[1274/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color.c.obj +[1275/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net_manager.c.obj +[1276/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_https_server.c.obj +[1277/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_qrcode.c.obj +[1278/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_animation.c.obj +[1279/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_drivers.c.obj +[1280/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_font.c.obj +[1281/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color_correction.c.obj +[1282/1344] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_dhcp_server.c.obj +[1283/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power.c.obj +[1284/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_monitor.c.obj +[1285/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_usb_mux.c.obj +[1286/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_effect.c.obj +[1287/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_preset.c.obj +[1288/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_hal.c.obj +[1289/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/qrcodegen/qrcodegen.c.obj +[1290/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_text.c.obj +[1291/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_gpio.c.obj +[1292/1344] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_automation.c.obj +[1293/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pin_manager.c.obj +[1294/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_fan.c.obj +[1295/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_device_ctrl.c.obj +[1296/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_i2c.c.obj +[1297/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/platform/esp32s3/ts_platform_s3.c.obj +[1298/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_policy.c.obj +[1299/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pwm.c.obj +[1300/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_uart.c.obj +[1301/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_temp_source.c.obj +[1302/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_adc.c.obj +[1303/1344] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_compute_monitor.c.obj +[1304/1344] Linking C static library esp-idf/esp_driver_touch_sens/libesp_driver_touch_sens.a +[1305/1344] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_image.c.obj +[1306/1344] Linking C static library esp-idf/esp_hid/libesp_hid.a +[1307/1344] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_spiffs.c.obj +[1308/1344] Linking C static library esp-idf/ts_api/libts_api.a +[1309/1344] Linking C static library esp-idf/esp_local_ctrl/libesp_local_ctrl.a +[1310/1344] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_spi.c.obj +[1311/1344] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_core_init.c.obj +[1312/1344] Linking C static library esp-idf/espcoredump/libespcoredump.a +[1313/1344] Linking C static library esp-idf/rt/librt.a +[1314/1344] Linking C static library esp-idf/nvs_sec_provider/libnvs_sec_provider.a +[1315/1344] Linking C static library esp-idf/perfmon/libperfmon.a +[1316/1344] Linking C static library esp-idf/mqtt/libmqtt.a +[1317/1344] Linking C static library esp-idf/esp_lcd/libesp_lcd.a +[1318/1344] Linking C static library esp-idf/touch_element/libtouch_element.a +[1319/1344] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage.c.obj +[1320/1344] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/main.c.obj +[1321/1344] Linking C static library esp-idf/ts_https/libts_https.a +[1322/1344] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_sd.c.obj +[1323/1344] Linking C static library esp-idf/usb/libusb.a +[1324/1344] Linking C static library esp-idf/wifi_provisioning/libwifi_provisioning.a +[1325/1344] Linking C static library esp-idf/ts_webui/libts_webui.a +[1326/1344] Building C object esp-idf/ts_pki_client/CMakeFiles/__idf_ts_pki_client.dir/src/ts_pki_client.c.obj +[1327/1344] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_services.c.obj +[1328/1344] Linking C static library esp-idf/ts_console/libts_console.a +[1329/1344] Linking C static library esp-idf/ts_ota/libts_ota.a +[1330/1344] Linking C static library esp-idf/ts_net/libts_net.a +[1331/1344] Linking C static library esp-idf/ts_led/libts_led.a +[1332/1344] Linking C static library esp-idf/ts_drivers/libts_drivers.a +[1333/1344] Linking C static library esp-idf/ts_hal/libts_hal.a +[1334/1344] Linking C static library esp-idf/ts_storage/libts_storage.a +[1335/1344] Linking C static library esp-idf/ts_pki_client/libts_pki_client.a +[1336/1344] Linking C static library esp-idf/main/libmain.a +[1337/1344] Performing build step for 'bootloader' +[1/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/util.c.obj +[2/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[3/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_lock.c.obj +[4/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[5/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[6/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_timestamp.c.obj +[7/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[8/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[9/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[10/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[11/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[12/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[13/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[14/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[15/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[16/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[17/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[18/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[19/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[20/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[21/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[22/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[23/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[24/123] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[25/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[26/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[27/123] Linking C static library esp-idf/log/liblog.a +[28/123] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[29/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[30/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[31/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[32/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[33/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[34/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[35/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[36/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[37/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[38/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[39/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[40/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[41/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[42/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[43/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[44/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[45/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[46/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[47/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[48/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[49/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[50/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[51/123] Linking C static library esp-idf/esp_rom/libesp_rom.a +[52/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[53/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_loader.c.obj +[54/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[55/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[56/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[57/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_soc.c.obj +[58/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console_loader.c.obj +[59/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console.c.obj +[60/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_panic.c.obj +[61/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[62/123] Linking C static library esp-idf/esp_common/libesp_common.a +[63/123] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[64/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[65/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[66/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[67/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[68/123] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[69/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[70/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[71/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[72/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[73/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[74/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_init.c.obj +[75/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_esp32s3.c.obj +[76/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[77/123] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[78/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[79/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[80/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[81/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[82/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[83/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[84/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[85/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[86/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[87/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[88/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[89/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[90/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[91/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[92/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[93/123] Linking C static library esp-idf/esp_system/libesp_system.a +[94/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[95/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[96/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[97/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[98/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[99/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[100/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[101/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[102/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[103/123] Generating project_elf_src_esp32s3.c +[104/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[105/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[106/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[107/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[108/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[109/123] Building C object CMakeFiles/bootloader.elf.dir/project_elf_src_esp32s3.c.obj +[110/123] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/bootloader_start.c.obj +[111/123] Linking C static library esp-idf/efuse/libefuse.a +[112/123] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[113/123] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[114/123] Linking C static library esp-idf/spi_flash/libspi_flash.a +[115/123] Building C object esp-idf/micro-ecc/CMakeFiles/__idf_micro-ecc.dir/uECC_verify_antifault.c.obj +[116/123] Linking C static library esp-idf/hal/libhal.a +[117/123] Linking C static library esp-idf/micro-ecc/libmicro-ecc.a +[118/123] Linking C static library esp-idf/soc/libsoc.a +[119/123] Linking C static library esp-idf/xtensa/libxtensa.a +[120/123] Linking C static library esp-idf/main/libmain.a +[121/123] Linking C executable bootloader.elf +[122/123] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-ssh-stack-diagnostic/build/bootloader/bootloader.bin +[123/123] cd /tmp/tianshan-ssh-stack-diagnostic/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ssh-stack-diagnostic/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[1338/1344] No install step for 'bootloader' +[1339/1344] Completed 'bootloader' +[1340/1344] Generating esp-idf/esp_system/ld/sections.ld +[1341/1344] Building C object CMakeFiles/TianShanOS.elf.dir/project_elf_src_esp32s3.c.obj +[1342/1344] Linking CXX executable TianShanOS.elf +[1343/1344] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-ssh-stack-diagnostic/build/TianShanOS.bin +[1344/1344] cd /tmp/tianshan-ssh-stack-diagnostic/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ssh-stack-diagnostic/build/partition_table/partition-table.bin /tmp/tianshan-ssh-stack-diagnostic/build/TianShanOS.bin +TianShanOS.bin binary size 0x259ee0 bytes. Smallest app partition is 0x300000 bytes. 0xa6120 bytes (22%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-ssh-stack-diagnostic/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-ssh-stack-diagnostic/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-ssh-stack-diagnostic/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-ssh-stack-diagnostic/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-ssh-stack-diagnostic/build/www.bin +or from the "/private/tmp/tianshan-ssh-stack-diagnostic/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ssh-poll-stack/diagnostic/sdkconfig-evidence.txt b/docs/repair/ssh-poll-stack/diagnostic/sdkconfig-evidence.txt new file mode 100644 index 0000000..fbc9b61 --- /dev/null +++ b/docs/repair/ssh-poll-stack/diagnostic/sdkconfig-evidence.txt @@ -0,0 +1,2877 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.5.2 Project Configuration +# +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_UHCI_SUPPORTED=y +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y +CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_SIMD_INSTRUCTION_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +CONFIG_SOC_CACHE_ACS_INVALID_STATE_ON_PANIC=y +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=5 +CONFIG_SOC_AHB_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=48 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=48 +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_SUPPORTS_PCM2PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_SUPPORTS_PDM2PCM=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_PCNT_GROUPS=1 +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_I80_NUM_BUSES=1 +CONFIG_SOC_LCDCAM_I80_BUS_WIDTH=16 +CONFIG_SOC_LCDCAM_RGB_NUM_PANELS=1 +CONFIG_SOC_LCDCAM_RGB_DATA_WIDTH=16 +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y +CONFIG_SOC_SDM_GROUPS=1 +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_SPI_SCT_SUPPORTED=y +CONFIG_SOC_SPI_SCT_REG_NUM=14 +CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y +CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA +CONFIG_SOC_MEMSPI_SRC_FREQ_120M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_TOUCH_SENSOR_VERSION=2 +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_MIN_CHAN_ID=1 +CONFIG_SOC_TOUCH_MAX_CHAN_ID=14 +CONFIG_SOC_TOUCH_SUPPORT_BENCHMARK=y +CONFIG_SOC_TOUCH_SUPPORT_SLEEP_WAKEUP=y +CONFIG_SOC_TOUCH_SUPPORT_WATERPROOF=y +CONFIG_SOC_TOUCH_SUPPORT_PROX_SENSING=y +CONFIG_SOC_TOUCH_SUPPORT_DENOISE_CHAN=y +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_MASK_FILTER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE=y +CONFIG_SOC_UHCI_NUM=1 +CONFIG_SOC_USB_OTG_PERIPH_NUM=1 +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_CLK_LP_FAST_SUPPORT_XTAL_D2=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY=y +CONFIG_SOC_MEMSPI_CORE_CLK_SHARED_WITH_PSRAM=y +CONFIG_SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_EXTERNAL_COEX_LEADER_TX_LINE=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_SDMMC_DELAY_PHASE_NUM=4 +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_CAM_PERIPH_NUM=1 +CONFIG_SOC_LCDCAM_CAM_DATA_WIDTH_MAX=16 +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_INIT_VERSION="5.5.2" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# + +# +# Bootloader manager +# +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + +# +# Application Rollback +# +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# end of Application Rollback + +# +# Recovery Bootloader and Rollback +# +# end of Recovery Bootloader and Rollback + +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# Log +# +CONFIG_BOOTLOADER_LOG_VERSION_1=y +CONFIG_BOOTLOADER_LOG_VERSION=1 +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format + +# +# Settings +# +CONFIG_BOOTLOADER_LOG_MODE_TEXT_EN=y +CONFIG_BOOTLOADER_LOG_MODE_TEXT=y +# end of Settings +# end of Log + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_OTG_NUM=3 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_SPI_FLASH_MMAP=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG=y +CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_HAS_VERSION=y +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y +CONFIG_ESP_ROM_CONSOLE_OUTPUT_SECONDARY=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="16MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_NONE is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +CONFIG_COMPILER_STACK_CHECK_MODE_ALL=y +CONFIG_COMPILER_STACK_CHECK=y +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_UART2 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set + +# +# Common Options +# + +# +# BLE Log +# +# CONFIG_BLE_LOG_ENABLED is not set +# end of BLE Log + +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set +# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set +# end of Common Options +# end of Bluetooth + +# +# Console Library +# +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library + +# +# Driver Configurations +# + +# +# Legacy TWAI Driver Configurations +# +# CONFIG_TWAI_SKIP_LEGACY_CONFLICT_CHECK is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of Legacy TWAI Driver Configurations + +# +# Legacy ADC Driver Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration + +# +# Legacy MCPWM Driver Configurations +# +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations + +# +# Legacy Timer Group Driver Configurations +# +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations + +# +# Legacy RMT Driver Configurations +# +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations + +# +# Legacy I2S Driver Configurations +# +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations + +# +# Legacy I2C Driver Configurations +# +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy PCNT Driver Configurations +# +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations + +# +# Legacy Temperature Sensor Driver Configurations +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Temperature Sensor Driver Configurations + +# +# Legacy Touch Sensor Driver Configurations +# +# CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Touch Sensor Driver Configurations +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +# CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration + +# +# Wireless Coexistence +# +CONFIG_ESP_COEX_ENABLED=y +# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# end of Common ESP-related + +# +# ESP-Driver:Camera Controller Configurations +# +# CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE is not set +# end of ESP-Driver:Camera Controller Configurations + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_CACHE_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM=y +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +CONFIG_MCPWM_ISR_HANDLER_IN_IRAM=y +# CONFIG_MCPWM_ISR_CACHE_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +CONFIG_MCPWM_OBJ_CACHE_SAFE=y +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations + +# +# ESP-Driver:PCNT Configurations +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# ESP-Driver:RMT Configurations +# +CONFIG_RMT_ENCODER_FUNC_IN_IRAM=y +CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM=y +CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM=y +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_TX_ISR_CACHE_SAFE is not set +# CONFIG_RMT_RX_ISR_CACHE_SAFE is not set +CONFIG_RMT_OBJ_CACHE_SAFE=y +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Touch Sensor Configurations +# +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# CONFIG_TOUCH_SKIP_FSM_CHECK is not set +# end of ESP-Driver:Touch Sensor Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations + +# +# ESP-Driver:TWAI Configurations +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +# CONFIG_TWAI_IO_FUNC_IN_IRAM is not set +# CONFIG_TWAI_ISR_CACHE_SAFE is not set +# CONFIG_TWAI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:TWAI Configurations + +# +# ESP-Driver:UART Configurations +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:UHCI Configurations +# +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + +# +# ESP-Driver:USB Serial/JTAG Configuration +# +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +CONFIG_ETH_SPI_ETHERNET_W5500=y +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 +CONFIG_HTTPD_MAX_URI_LEN=256 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +CONFIG_HTTPD_WS_SUPPORT=y +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# CONFIG_HTTPD_WS_PRE_HANDSHAKE_CB_SUPPORT is not set +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +# CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 +# CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK is not set +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# Chip revision +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-S3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_ESP_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configurations +# +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +CONFIG_GDMA_ISR_HANDLER_IN_IRAM=y +CONFIG_GDMA_OBJ_DRAM_SAFE=y +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configurations + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config + +# +# Power Supplier +# + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +CONFIG_ESP_BROWNOUT_USE_INTR=y +# end of Brownout Detector +# end of Power Supplier + +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +CONFIG_ESP_INTR_IN_IRAM=y +# end of Hardware Settings + +# +# ESP-Driver:LCD Controller Configurations +# +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:LCD Controller Configurations + +# +# ESP-MM: Memory Management Configurations +# +# CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS is not set +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# PHY +# +CONFIG_ESP_PHY_ENABLED=y +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# CONFIG_ESP_PHY_DEBUG is not set +# end of PHY + +# +# Power Management +# +CONFIG_PM_SLEEP_FUNC_IN_IRAM=y +# CONFIG_PM_ENABLE is not set +CONFIG_PM_SLP_IRAM_OPT=y +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# +CONFIG_SPIRAM=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_XIP_FROM_PSRAM is not set +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED=80 +# CONFIG_SPIRAM_ECC_ENABLE is not set +CONFIG_SPIRAM_BOOT_HW_INIT=y +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=64 +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=16384 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set +# end of SPI RAM config +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP-ROM +# +CONFIG_ESP_ROM_PRINT_IN_IRAM=y +# end of ESP-ROM + +# +# ESP Security Specific +# +# end of ESP Security Specific + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +CONFIG_ESP_SYSTEM_IN_IRAM=y +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4608 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=30 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_BBPLL_RECALIB=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_ENABLE=y +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# ESP Timer (High Resolution Timer) +# +CONFIG_ESP_TIMER_IN_IRAM=y +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=16 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=3 +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=8 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_ENABLE_SAE_H2E=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +# CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set +# end of WPS Configuration Options + +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y +# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=4 +# CONFIG_FATFS_LFN_NONE is not set +CONFIG_FATFS_LFN_HEAP=y +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_MAX_LFN=255 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +# CONFIG_FATFS_API_ENCODING_UTF_8 is not set +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set + +# +# File system free space calculation behavior +# +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=1000 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3072 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U32=y +# CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U64 is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +# CONFIG_FREERTOS_FPU_IN_ISR is not set +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y +# end of Extra + +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=2 +CONFIG_FREERTOS_IN_IRAM=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +# CONFIG_HEAP_POISONING_DISABLED is not set +CONFIG_HEAP_POISONING_LIGHT=y +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# +CONFIG_LOG_VERSION_1=y +# CONFIG_LOG_VERSION_2 is not set +CONFIG_LOG_VERSION=1 + +# +# Log Level +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +# CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT is not set +CONFIG_LOG_MAXIMUM_LEVEL_DEBUG=y +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=4 + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Format + +# +# Settings +# +CONFIG_LOG_MODE_TEXT_EN=y +CONFIG_LOG_MODE_TEXT=y +# end of Settings + +CONFIG_LOG_IN_IRAM=y +# end of Log + +# +# LWIP +# +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="rm01" +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=16 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +CONFIG_LWIP_IP_FORWARD=y +CONFIG_LWIP_IPV4_NAPT=y +CONFIG_LWIP_IPV4_NAPT_PORTMAP=y +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=8 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=69 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=4096 +CONFIG_LWIP_TCP_WND_DEFAULT=4096 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=0 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set +# CONFIG_LWIP_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=3 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# CONFIG_LWIP_USE_ESP_GETADDRINFO is not set +# end of DNS + +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_NONE=y +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_DEFAULT is not set +# CONFIG_LWIP_HOOK_DHCP_EXTRA_OPTION_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +# CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC is not set +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=8192 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +CONFIG_MBEDTLS_HKDF_C=y +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set +# end of mbedTLS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# LibC +# +CONFIG_LIBC_NEWLIB=y +CONFIG_LIBC_MISC_IN_IRAM=y +CONFIG_LIBC_LOCKS_PLACE_IN_IRAM=y +CONFIG_LIBC_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_LIBC_STDOUT_LINE_ENDING_LF is not set +# CONFIG_LIBC_STDOUT_LINE_ENDING_CR is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_LIBC_STDIN_LINE_ENDING_LF is not set +CONFIG_LIBC_STDIN_LINE_ENDING_CR=y +# CONFIG_LIBC_NEWLIB_NANO_FORMAT is not set +CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_LIBC_TIME_SYSCALL_USE_RTC is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_HRT is not set +# CONFIG_LIBC_TIME_SYSCALL_USE_NONE is not set +# end of LibC + +CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y + +# +# NVS +# +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM=y +# end of NVS + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel + +# CONFIG_OPENTHREAD_DEBUG is not set +# end of OpenThread + +# +# Protocomm +# +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_HPM_ENA is not set +CONFIG_SPI_FLASH_HPM_AUTO=y +# CONFIG_SPI_FLASH_HPM_DIS is not set +CONFIG_SPI_FLASH_HPM_ON=y +CONFIG_SPI_FLASH_HPM_DC_AUTO=y +# CONFIG_SPI_FLASH_HPM_DC_DISABLE is not set +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set +CONFIG_SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM=y +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORT_ENABLED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Ultra Low Power (ULP) Co-processor +# +# CONFIG_ULP_COPROC_ENABLED is not set + +# +# ULP Debugging Options +# +# end of ULP Debugging Options +# end of Ultra Low Power (ULP) Co-processor + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# CONFIG_UNITY_TEST_ORDER_BY_FILE_PATH_AND_LINE is not set +# end of Unity unit testing library + +# +# USB-OTG +# +CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE=256 +CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED=y +# CONFIG_USB_HOST_HW_BUFFER_BIAS_IN is not set +# CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT is not set + +# +# Hub Driver Configuration +# + +# +# Root Port configuration +# +CONFIG_USB_HOST_DEBOUNCE_DELAY_MS=250 +CONFIG_USB_HOST_RESET_HOLD_MS=30 +CONFIG_USB_HOST_RESET_RECOVERY_MS=30 +CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS=10 +# end of Root Port configuration + +# CONFIG_USB_HOST_HUBS_SUPPORTED is not set +# end of Hub Driver Configuration + +# CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK is not set +CONFIG_USB_OTG_SUPPORTED=y +# end of USB-OTG + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=16 + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y +# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set +# end of Wi-Fi Provisioning Manager + +# +# TianShanOS API Configuration +# +CONFIG_TS_API_MAX_ENDPOINTS=288 +CONFIG_TS_API_MAX_NAME_LENGTH=64 +CONFIG_TS_API_ENABLE_AUTH=y +# end of TianShanOS API Configuration + +# +# TianShanOS Automation Engine +# +CONFIG_TS_AUTOMATION_ENABLED=y +CONFIG_TS_AUTOMATION_CONFIG_PATH="/sdcard/config/automation.json" +CONFIG_TS_AUTOMATION_MAX_SOURCES=16 +CONFIG_TS_AUTOMATION_MAX_RULES=32 +CONFIG_TS_AUTOMATION_MAX_VARIABLES=512 +CONFIG_TS_AUTOMATION_TASK_STACK_SIZE=4096 +CONFIG_TS_AUTOMATION_TASK_PRIORITY=5 +# end of TianShanOS Automation Engine + +# +# TianShanOS PKI Certificate +# +CONFIG_TS_CERT_ENABLED=y +CONFIG_TS_CERT_DEFAULT_ORG="TianShanOS" +CONFIG_TS_CERT_DEFAULT_OU="Device" +CONFIG_TS_CERT_AUTO_INIT=y +CONFIG_TS_CERT_EXPIRY_WARNING_DAYS=30 +# end of TianShanOS PKI Certificate + +# +# TianShanOS Config Pack +# +CONFIG_TS_CONFIG_PACK_ENABLED=y +CONFIG_TS_CONFIG_PACK_MAX_SIZE=65536 +CONFIG_TS_CONFIG_PACK_VERIFY_CERT_CHAIN=y +# CONFIG_TS_CONFIG_PACK_REQUIRE_OFFICIAL_SIG is not set +# end of TianShanOS Config Pack + +# +# TianShanOS Console Configuration +# +CONFIG_TS_CONSOLE_MAX_LINE_LENGTH=256 +CONFIG_TS_CONSOLE_MAX_HISTORY=50 +CONFIG_TS_CONSOLE_TASK_PRIORITY=5 +CONFIG_TS_CONSOLE_TASK_STACK_SIZE=6144 +CONFIG_TS_CONSOLE_DEFAULT_PROMPT="tianshan> " +CONFIG_TS_CONSOLE_ENABLE_COLORS=y +CONFIG_TS_CONSOLE_HISTORY_FILE="/sdcard/.console_history" +# end of TianShanOS Console Configuration + +# +# TianShanOS Drivers Configuration +# +CONFIG_TS_DRIVERS_FAN_ENABLE=y +CONFIG_TS_DRIVERS_FAN_PWM_FREQ=25000 +CONFIG_TS_DRIVERS_FAN_TEMP_UPDATE_MS=1000 +CONFIG_TS_DRIVERS_POWER_ENABLE=y +CONFIG_TS_DRIVERS_POWER_ADC_SAMPLES=16 +CONFIG_TS_DRIVERS_DEVICE_ENABLE=y +CONFIG_TS_DRIVERS_AGX_POWER_ON_DELAY_MS=100 +CONFIG_TS_DRIVERS_USB_MUX_ENABLE=y +# end of TianShanOS Drivers Configuration + +# +# TianShanOS HAL Configuration +# +CONFIG_TS_HAL_MAX_PINS=48 +CONFIG_TS_HAL_MAX_GPIO_HANDLES=32 +CONFIG_TS_HAL_MAX_PWM_HANDLES=8 +CONFIG_TS_HAL_MAX_I2C_HANDLES=4 +CONFIG_TS_HAL_MAX_SPI_HANDLES=4 +CONFIG_TS_HAL_MAX_UART_HANDLES=3 +CONFIG_TS_HAL_MAX_ADC_HANDLES=8 +CONFIG_TS_HAL_PIN_CONFIG_PATH="/sdcard/config/pins.json" +CONFIG_TS_HAL_ENABLE_PIN_CONFLICT_CHECK=y +CONFIG_TS_HAL_PWM_DEFAULT_FREQ=25000 +CONFIG_TS_HAL_PWM_DEFAULT_RESOLUTION=8 +# end of TianShanOS HAL Configuration + +# +# TianShanOS HTTPS Server +# +# CONFIG_TS_HTTPS_ENABLED is not set +# end of TianShanOS HTTPS Server + +# +# TianShanOS LED Configuration +# +CONFIG_TS_LED_MAX_DEVICES=8 +CONFIG_TS_LED_MAX_LAYERS=8 +CONFIG_TS_LED_DEFAULT_BRIGHTNESS=128 +CONFIG_TS_LED_TASK_PRIORITY=5 +CONFIG_TS_LED_TASK_STACK_SIZE=3072 +CONFIG_TS_LED_REFRESH_RATE_HZ=60 + +# +# Touch LED Settings +# +CONFIG_TS_LED_TOUCH_COUNT=1 +CONFIG_TS_LED_TOUCH_DEFAULT_BRIGHTNESS=80 +# end of Touch LED Settings + +# +# Board LED Settings +# +CONFIG_TS_LED_BOARD_COUNT=28 +CONFIG_TS_LED_BOARD_DEFAULT_BRIGHTNESS=60 +# end of Board LED Settings + +# +# Matrix LED Settings +# +CONFIG_TS_LED_MATRIX_WIDTH=32 +CONFIG_TS_LED_MATRIX_HEIGHT=32 +CONFIG_TS_LED_MATRIX_DEFAULT_BRIGHTNESS=50 +# end of Matrix LED Settings + +# +# Image Support +# +CONFIG_TS_LED_ENABLE_BMP=y +CONFIG_TS_LED_ENABLE_PNG=y +CONFIG_TS_LED_ENABLE_JPG=y +CONFIG_TS_LED_ENABLE_GIF=y +# end of Image Support +# end of TianShanOS LED Configuration + +# +# TianShanOS Network Configuration +# +CONFIG_TS_NET_ETHERNET_ENABLE=y +CONFIG_TS_NET_ETH_SPI_HOST=2 +# CONFIG_TS_NET_WIFI_ENABLE is not set +CONFIG_TS_NET_DHCP_SERVER_ENABLE=y +# CONFIG_TS_NET_MDNS_ENABLE is not set +CONFIG_TS_NET_HTTP_SERVER_ENABLE=y +CONFIG_TS_NET_HTTP_PORT=80 +CONFIG_TS_NET_HTTPS_PORT=443 +# end of TianShanOS Network Configuration + +# +# TianShanOS OTA Configuration +# +CONFIG_TS_OTA_ENABLED=y +CONFIG_TS_OTA_ROLLBACK_TIMEOUT=60 +CONFIG_TS_OTA_HTTPS_ENABLED=y +CONFIG_TS_OTA_SDCARD_ENABLED=y +CONFIG_TS_OTA_WEBUI_UPLOAD_ENABLED=y +CONFIG_TS_OTA_BUFFER_SIZE=8192 +# CONFIG_TS_OTA_VERIFY_SIGNATURE is not set +# CONFIG_TS_OTA_ANTI_ROLLBACK is not set +CONFIG_TS_OTA_VERSION_CHECK=y +CONFIG_TS_OTA_DEFAULT_URL="https://ota.example.com/tianshanos" +CONFIG_TS_OTA_TASK_STACK_SIZE=8192 +CONFIG_TS_OTA_TASK_PRIORITY=5 +# end of TianShanOS OTA Configuration + +# +# TianShanOS Security Configuration +# +CONFIG_TS_SECURITY_ENABLE=y +CONFIG_TS_SECURITY_KEY_STORAGE_NVS=y +CONFIG_TS_SECURITY_MTLS_ENABLE=y +CONFIG_TS_SECURITY_TOKEN_EXPIRE_SEC=86400 +CONFIG_TS_SECURITY_MAX_SESSIONS=8 +CONFIG_TS_SECURITY_PERMISSION_LEVELS=4 +CONFIG_TS_SSH_LOG_WATCH_MAX=32 +# end of TianShanOS Security Configuration + +# +# TianShanOS Storage Configuration +# +CONFIG_TS_STORAGE_ENABLE_SPIFFS=y +CONFIG_TS_STORAGE_SPIFFS_MOUNT_POINT="/spiffs" +CONFIG_TS_STORAGE_SPIFFS_PARTITION="storage" +CONFIG_TS_STORAGE_SPIFFS_MAX_FILES=5 +CONFIG_TS_STORAGE_ENABLE_SD=y +CONFIG_TS_STORAGE_SD_MOUNT_POINT="/sdcard" +CONFIG_TS_STORAGE_SD_MAX_FREQ_KHZ=20000 +# CONFIG_TS_STORAGE_SD_MODE_SPI is not set +# CONFIG_TS_STORAGE_SD_MODE_SDIO_1BIT is not set +CONFIG_TS_STORAGE_SD_MODE_SDIO_4BIT=y + +# +# SD Card GPIO Configuration +# +CONFIG_TS_STORAGE_SD_CMD_GPIO=15 +CONFIG_TS_STORAGE_SD_CLK_GPIO=16 +CONFIG_TS_STORAGE_SD_D0_GPIO=4 +CONFIG_TS_STORAGE_SD_D1_GPIO=5 +CONFIG_TS_STORAGE_SD_D2_GPIO=6 +CONFIG_TS_STORAGE_SD_D3_GPIO=7 +# end of SD Card GPIO Configuration +# end of TianShanOS Storage Configuration + +# +# TianShanOS WebUI Configuration +# +CONFIG_TS_WEBUI_ENABLE=y +CONFIG_TS_WEBUI_API_PREFIX="/api/v1" +CONFIG_TS_WEBUI_WS_ENABLE=y +CONFIG_TS_WEBUI_WS_MAX_CLIENTS=8 +CONFIG_TS_WEBUI_TERMINAL_OUTPUT_BUF_SIZE=32768 +CONFIG_TS_WEBUI_AUTH_REQUIRED=y +CONFIG_TS_WEBUI_CORS_ENABLE=y +CONFIG_TS_WEBUI_STATIC_PATH="/www" +# end of TianShanOS WebUI Configuration + +# +# TianShanOS Configuration Management +# +CONFIG_TS_CONFIG_ENABLE=y +CONFIG_TS_CONFIG_MAX_KEY_LENGTH=64 +CONFIG_TS_CONFIG_MAX_VALUE_SIZE=512 +CONFIG_TS_CONFIG_MAX_LISTENERS=16 +CONFIG_TS_CONFIG_NVS_NAMESPACE="ts_config" + +# +# Configuration Backends +# +CONFIG_TS_CONFIG_NVS_BACKEND=y +CONFIG_TS_CONFIG_FILE_BACKEND=y +CONFIG_TS_CONFIG_FILE_PATH="/sdcard/config" +CONFIG_TS_CONFIG_FILE_FORMAT_JSON=y +# end of Configuration Backends + +# +# Configuration Priorities +# +CONFIG_TS_CONFIG_PRIORITY_CLI=100 +CONFIG_TS_CONFIG_PRIORITY_NVS=80 +CONFIG_TS_CONFIG_PRIORITY_FILE=60 +CONFIG_TS_CONFIG_PRIORITY_DEFAULT=0 +# end of Configuration Priorities + +CONFIG_TS_CONFIG_AUTO_SAVE=y +CONFIG_TS_CONFIG_AUTO_SAVE_DELAY_MS=1000 +# CONFIG_TS_CONFIG_DEBUG is not set +# end of TianShanOS Configuration Management + +# +# TianShanOS Logging +# +CONFIG_TS_LOG_ENABLE=y +# CONFIG_TS_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_TS_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_TS_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_TS_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_TS_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_TS_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_TS_LOG_DEFAULT_LEVEL=3 +CONFIG_TS_LOG_COLORS=y +CONFIG_TS_LOG_TIMESTAMP=y +CONFIG_TS_LOG_TASK_NAME=y + +# +# Log Outputs +# +CONFIG_TS_LOG_OUTPUT_CONSOLE=y +# CONFIG_TS_LOG_OUTPUT_FILE is not set +CONFIG_TS_LOG_OUTPUT_BUFFER=y +CONFIG_TS_LOG_BUFFER_SIZE=500 +CONFIG_TS_LOG_CAPTURE_ESP_LOG=y +# end of Log Outputs + +CONFIG_TS_LOG_TAG_MAX_LENGTH=16 +CONFIG_TS_LOG_MESSAGE_MAX_LENGTH=256 +# end of TianShanOS Logging + +# +# TianShanOS Event System +# +CONFIG_TS_EVENT_ENABLE=y +CONFIG_TS_EVENT_LOOP_TASK_PRIORITY=5 +CONFIG_TS_EVENT_LOOP_TASK_STACK_SIZE=4096 +CONFIG_TS_EVENT_QUEUE_SIZE=32 +CONFIG_TS_EVENT_MAX_HANDLERS=64 +CONFIG_TS_EVENT_MAX_EVENT_TYPES=64 +CONFIG_TS_EVENT_DATA_MAX_SIZE=256 +CONFIG_TS_EVENT_ENABLE_STATS=y +# CONFIG_TS_EVENT_ENABLE_TRACING is not set +# end of TianShanOS Event System + +# +# TianShanOS Service Management +# +CONFIG_TS_SERVICE_ENABLE=y +CONFIG_TS_SERVICE_MAX_SERVICES=32 +CONFIG_TS_SERVICE_NAME_MAX_LENGTH=32 +CONFIG_TS_SERVICE_MAX_DEPENDENCIES=8 +CONFIG_TS_SERVICE_STARTUP_TIMEOUT_MS=30000 +CONFIG_TS_SERVICE_SHUTDOWN_TIMEOUT_MS=10000 + +# +# Startup Phases +# +CONFIG_TS_SERVICE_PHASE_PLATFORM_PRIORITY=10 +CONFIG_TS_SERVICE_PHASE_CORE_PRIORITY=20 +CONFIG_TS_SERVICE_PHASE_HAL_PRIORITY=30 +CONFIG_TS_SERVICE_PHASE_DRIVER_PRIORITY=40 +CONFIG_TS_SERVICE_PHASE_NETWORK_PRIORITY=50 +CONFIG_TS_SERVICE_PHASE_SECURITY_PRIORITY=60 +CONFIG_TS_SERVICE_PHASE_SERVICE_PRIORITY=70 +CONFIG_TS_SERVICE_PHASE_UI_PRIORITY=80 +# end of Startup Phases + +CONFIG_TS_SERVICE_ENABLE_WATCHDOG=y +CONFIG_TS_SERVICE_WATCHDOG_TIMEOUT_MS=60000 +# CONFIG_TS_SERVICE_DEBUG is not set +# end of TianShanOS Service Management + +# +# JPEG Decoder +# +CONFIG_JD_USE_ROM=y +# end of JPEG Decoder + +# +# ESP WebSocket client +# +# CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER is not set +# CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK is not set +# end of ESP WebSocket client + +# +# mDNS +# +CONFIG_MDNS_MAX_INTERFACES=3 +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_ACTION_QUEUE_LEN=16 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +# CONFIG_MDNS_TASK_AFFINITY_CPU1 is not set +CONFIG_MDNS_TASK_AFFINITY=0x0 + +# +# MDNS Memory Configuration +# +# CONFIG_MDNS_TASK_CREATE_FROM_SPIRAM is not set +CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL=y +# CONFIG_MDNS_MEMORY_ALLOC_SPIRAM is not set +CONFIG_MDNS_MEMORY_ALLOC_INTERNAL=y +# CONFIG_MDNS_MEMORY_CUSTOM_IMPL is not set +# end of MDNS Memory Configuration + +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +# CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES is not set +# CONFIG_MDNS_ENABLE_DEBUG_PRINTS is not set +CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +# CONFIG_MDNS_RESPOND_REVERSE_QUERIES is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y + +# +# MDNS Predefined interfaces +# +CONFIG_MDNS_PREDEF_NETIF_STA=y +CONFIG_MDNS_PREDEF_NETIF_AP=y +CONFIG_MDNS_PREDEF_NETIF_ETH=y +# end of MDNS Predefined interfaces +# end of mDNS +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +CONFIG_FLASHMODE_QIO=y +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +# CONFIG_STACK_CHECK_NONE is not set +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +CONFIG_STACK_CHECK_ALL=y +CONFIG_STACK_CHECK=y +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_EXTERNAL_COEX_ENABLE is not set +# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set +# CONFIG_CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +CONFIG_OTA_ALLOW_HTTP=y +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=3584 +CONFIG_MAIN_TASK_STACK_SIZE=4608 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=30 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=4 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=8 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=3072 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=8 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=4096 +CONFIG_TCP_WND_DEFAULT=4096 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options diff --git a/docs/repair/ssh-poll-stack/manifest.json b/docs/repair/ssh-poll-stack/manifest.json new file mode 100644 index 0000000..be0ec20 --- /dev/null +++ b/docs/repair/ssh-poll-stack/manifest.json @@ -0,0 +1,72 @@ +{ + "head": "3a19128d8638771c958fe47df1d6a7d339a10a4c", + "before_source": { + "path": "/tmp/ssh-poll-before.c", + "sha256": "cb8f801a18672c24636fe744cacf0f1e0379f75b579bcd4869bb9c9d8e541949" + }, + "after_source_sha256": "e53fa635a9775b571a143f9e54fdfd329eeb501345d878833b6567a3f41b21bb", + "builds": { + "candidate": { + "dir": "/tmp/tianshan-ssh-stack-candidate/build", + "config_sha256": "1340e033b5865e39dd6b8c3516dffb27d01da5aff41127c69b583cbfb99acef0", + "vendor": [ + { + "file": "xterm.min.js", + "sha256": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "raw": 283670, + "gzip": 65684 + }, + { + "file": "xterm.css", + "sha256": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "raw": 5383, + "gzip": 2037 + }, + { + "file": "fit.min.js", + "sha256": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "raw": 1789, + "gzip": 822 + } + ], + "flash_files": { + "0x0": "bootloader/bootloader.bin", + "0x20000": "TianShanOS.bin", + "0x8000": "partition_table/partition-table.bin", + "0x16000": "ota_data_initial.bin", + "0x6a0000": "www.bin" + } + }, + "diagnostic": { + "dir": "/tmp/tianshan-ssh-stack-diagnostic/build", + "config_sha256": "cf1c9534a0686d9ce89fd3b31e3f1db2b8f984d1b646bad8bd467afae2c05e7c", + "vendor": [ + { + "file": "xterm.min.js", + "sha256": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "raw": 283670, + "gzip": 65684 + }, + { + "file": "xterm.css", + "sha256": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "raw": 5383, + "gzip": 2037 + }, + { + "file": "fit.min.js", + "sha256": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "raw": 1789, + "gzip": 822 + } + ], + "flash_files": { + "0x0": "bootloader/bootloader.bin", + "0x20000": "TianShanOS.bin", + "0x8000": "partition_table/partition-table.bin", + "0x16000": "ota_data_initial.bin", + "0x6a0000": "www.bin" + } + } + } +} diff --git a/docs/repair/ssh-poll-stack/optimized-xterm.txt b/docs/repair/ssh-poll-stack/optimized-xterm.txt new file mode 100644 index 0000000..b0a08e5 --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized-xterm.txt @@ -0,0 +1,10 @@ +✔ en-US: cold offline real xterm and terminal lifecycle (969.883084ms) +✔ zh-CN: cold offline real xterm and terminal lifecycle (770.501209ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1926.154667 diff --git a/docs/repair/ssh-poll-stack/optimized/browser.json b/docs/repair/ssh-poll-stack/optimized/browser.json new file mode 100644 index 0000000..a3ad5bd --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized/browser.json @@ -0,0 +1,31 @@ +[ + { + "name": "browser", + "command": [ + "npm", + "run", + "test:browser", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "name": "cross-browser-en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + }, + { + "name": "cross-browser-zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/optimized/browser.log b/docs/repair/ssh-poll-stack/optimized/browser.log new file mode 100644 index 0000000..7cc43c3 --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized/browser.log @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (707.620417ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (325.03525ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (345.495583ms) +✔ en-US: initial language failure blocks controls and retry recovers (382.403125ms) +✔ delayed language package and rapid switches keep the latest requested language (302.962125ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (366.256875ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (299.486791ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (329.599959ms) +✔ initial delayed language keeps controls inert until the real package arrives (243.382958ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (373.290458ms) +✔ terminal can initialize after failed resource load using newly served resources (390.703417ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (643.640208ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (179.028166ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (232.798042ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (295.160792ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (284.695ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (271.764041ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (179.900042ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (195.278792ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (171.976583ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (188.442416ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (181.813125ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (199.995916ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (270.188833ms) +✔ R3: late validation cannot revive an old apply entry en-US (275.258084ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (261.444875ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (256.402625ms) +✔ R6: fixed upload destination and separate refresh failure en-US (238.494167ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (263.223375ms) +✔ R2: authenticated startup initializes once (280.434584ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (239.107833ms) +✔ R4/R5: newest result wins over late success and late failure (254.992542ms) +✔ R3: overlapping writes to one path cannot claim current verified content (241.551542ms) +✔ R2: disposed page only removes its dashboard callback (267.447041ms) +✔ R2: stale finally cannot unlock the new page read (249.192417ms) +✔ R1: delayed sign-out does not clear a newer sign-in (258.742458ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (309.668791ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (392.888208ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 7494.396541 diff --git a/docs/repair/ssh-poll-stack/optimized/cross-browser-en-US.json b/docs/repair/ssh-poll-stack/optimized/cross-browser-en-US.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized/cross-browser-en-US.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/optimized/cross-browser-en-US.log b/docs/repair/ssh-poll-stack/optimized/cross-browser-en-US.log new file mode 100644 index 0000000..f832b4b --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized/cross-browser-en-US.log @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ssh-poll-stack/optimized/cross-browser-zh-CN.json b/docs/repair/ssh-poll-stack/optimized/cross-browser-zh-CN.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized/cross-browser-zh-CN.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/optimized/cross-browser-zh-CN.log b/docs/repair/ssh-poll-stack/optimized/cross-browser-zh-CN.log new file mode 100644 index 0000000..1f8c8bd --- /dev/null +++ b/docs/repair/ssh-poll-stack/optimized/cross-browser-zh-CN.log @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ssh-poll-stack/publication-gate.md b/docs/repair/ssh-poll-stack/publication-gate.md new file mode 100644 index 0000000..f4f3205 --- /dev/null +++ b/docs/repair/ssh-poll-stack/publication-gate.md @@ -0,0 +1,16 @@ +# PR #42 本轮提交前检查 + +结论:可以推送,限本轮 SSH poller 最小修复及证据。 + +- 远端 PR head 与本地基线均为 3a19128d8638771c958fe47df1d6a7d339a10a4c,分支一致。 +- 生产差异仅 8192 bytes PSRAM stack 预算与配套 vTaskDeleteWithCaps;不改变输出缓冲、优先级、协议、operation 或保护策略。 +- 当前生产文件 SHA256 与 manifest 中构建输入一致:e53fa635a9775b571a143f9e54fdfd329eeb501345d878833b6567a3f41b21bb。未因提交准备修改生产输入,未重复完整构建。 +- 本次重跑 `IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf bash tests/ws_subscriptions/run_operation_adapter.sh` 退出0;涵盖生产调用方及10次关闭/回收,ASan/UBSan。首次未设 IDF_PATH 被脚本拒绝,补齐固定 SDK 路径后重跑。 +- 现存固定 SDK 两版构建及真机证据见 README;新 head CI 必须单独查看,不沿用旧 head 绿灯。 +- 凭据模式检查未发现提交材料含真实 SSH 密码、Bearer token 或明文 token。无固件二进制、node_modules 或构建目录纳入提交。 +- 排除原有 output/、tmp/、docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt,保留原地。 +- 余下边界:30秒安全 debug_tick 不等于低压关机测试;未直接读取真机 operation ledger;小幅堆净差未归因,不能宣称零泄漏。多终端抢占现象如实记录。 + +用户授权更新 PR;本轮不合并、不打 tag、不发布。 + +暂存检查补充:全量 `git diff --cached --check` 报告原始构建/串口日志的尾随空格、CRLF,以及 change.patch 的空白上下文行。保留这些证据原文,不为消除格式告警改写日志;排除上述原始 .log、crash.txt、change.patch 后,生产、测试及文档差异检查通过。 diff --git a/docs/repair/ssh-poll-stack/requests-source-en-US.json b/docs/repair/ssh-poll-stack/requests-source-en-US.json new file mode 100644 index 0000000..59325af --- /dev/null +++ b/docs/repair/ssh-poll-stack/requests-source-en-US.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/en-US.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/requests-source-zh-CN.json b/docs/repair/ssh-poll-stack/requests-source-zh-CN.json new file mode 100644 index 0000000..ef547b7 --- /dev/null +++ b/docs/repair/ssh-poll-stack/requests-source-zh-CN.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/adapter.log b/docs/repair/ssh-poll-stack/results/adapter.log new file mode 100644 index 0000000..540987e --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/adapter.log @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=94 diff --git a/docs/repair/ssh-poll-stack/results/browser.json b/docs/repair/ssh-poll-stack/results/browser.json new file mode 100644 index 0000000..a3ad5bd --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/browser.json @@ -0,0 +1,31 @@ +[ + { + "name": "browser", + "command": [ + "npm", + "run", + "test:browser", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "name": "cross-browser-en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + }, + { + "name": "cross-browser-zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/browser.log b/docs/repair/ssh-poll-stack/results/browser.log new file mode 100644 index 0000000..bb86c35 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/browser.log @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (1036.163125ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (263.119625ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (680.450334ms) +✔ en-US: initial language failure blocks controls and retry recovers (1047.581292ms) +✔ delayed language package and rapid switches keep the latest requested language (1048.449708ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (1051.696375ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (644.404208ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (678.549334ms) +✔ initial delayed language keeps controls inert until the real package arrives (538.8575ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (1110.103ms) +✔ terminal can initialize after failed resource load using newly served resources (1211.584709ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (979.633417ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (229.996375ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (178.120542ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (629.053625ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (1071.191417ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (1020.171583ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (675.362917ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (692.278917ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (375.477541ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (418.878958ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (403.24225ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (441.100041ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (1124.800667ms) +✔ R3: late validation cannot revive an old apply entry en-US (1046.777ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (899.396458ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (404.605125ms) +✔ R6: fixed upload destination and separate refresh failure en-US (1023.500125ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (2134.709708ms) +✔ R2: authenticated startup initializes once (2248.490209ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (1706.593ms) +✔ R4/R5: newest result wins over late success and late failure (1642.570084ms) +✔ R3: overlapping writes to one path cannot claim current verified content (1668.063833ms) +✔ R2: disposed page only removes its dashboard callback (1266.6165ms) +✔ R2: stale finally cannot unlock the new page read (666.206542ms) +✔ R1: delayed sign-out does not clear a newer sign-in (264.284834ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (317.434333ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (1109.395041ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 25381.373 diff --git a/docs/repair/ssh-poll-stack/results/certificate.log b/docs/repair/ssh-poll-stack/results/certificate.log new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/certificate.log @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ssh-poll-stack/results/control.log b/docs/repair/ssh-poll-stack/results/control.log new file mode 100644 index 0000000..4a2046f --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/control.log @@ -0,0 +1,5 @@ +PASS actual WS controls: all four foreign controls rejected, owner controls work; borrowed original pinned, fd/epoch/server reuse and late close isolated; owner stop drains +PASS accepted cancellation persists through task/key/create/connect/auth; cancel/submit claim both orders and result freeze tested; duplicate/old/zero IDs isolated +PASS USER/TIMEOUT/MATCH keep distinct results; service stop busy does not cancel business, accepted user intent survives stop retry and all resource ledgers drain +PASS output failure seals observation without cancelling business; later explicit cancel still reaches original executor without rewriting terminal; earlier timeout retains reason +PASS actual ssh.cancel API exact-ID validation and accepted-intent response; ended operations reject without wildcard control diff --git a/docs/repair/ssh-poll-stack/results/cross-browser-en-US.json b/docs/repair/ssh-poll-stack/results/cross-browser-en-US.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-browser-en-US.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/cross-browser-en-US.log b/docs/repair/ssh-poll-stack/results/cross-browser-en-US.log new file mode 100644 index 0000000..f832b4b --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-browser-en-US.log @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ssh-poll-stack/results/cross-browser-zh-CN.json b/docs/repair/ssh-poll-stack/results/cross-browser-zh-CN.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-browser-zh-CN.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/cross-browser-zh-CN.log b/docs/repair/ssh-poll-stack/results/cross-browser-zh-CN.log new file mode 100644 index 0000000..1f8c8bd --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-browser-zh-CN.log @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ssh-poll-stack/results/cross-node-en-US.json b/docs/repair/ssh-poll-stack/results/cross-node-en-US.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-node-en-US.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/cross-node-en-US.log b/docs/repair/ssh-poll-stack/results/cross-node-en-US.log new file mode 100644 index 0000000..7c3e1b4 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-node-en-US.log @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ssh-poll-stack/results/cross-node-zh-CN.json b/docs/repair/ssh-poll-stack/results/cross-node-zh-CN.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-node-zh-CN.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/cross-node-zh-CN.log b/docs/repair/ssh-poll-stack/results/cross-node-zh-CN.log new file mode 100644 index 0000000..4699bd2 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/cross-node-zh-CN.log @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ssh-poll-stack/results/f1_f2.log b/docs/repair/ssh-poll-stack/results/f1_f2.log new file mode 100644 index 0000000..854d7e5 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/f1_f2.log @@ -0,0 +1,23 @@ +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F2: protection transition survives ordinary log saturation +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS original peer and operation identity isolation across reconnect +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ssh-poll-stack/results/host.json b/docs/repair/ssh-poll-stack/results/host.json new file mode 100644 index 0000000..0454bdc --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/host.json @@ -0,0 +1,108 @@ +[ + { + "name": "host", + "command": [ + "bash", + "tests/ws_subscriptions/run_host.sh" + ], + "exit": 0 + }, + { + "name": "operation", + "command": [ + "bash", + "tests/ws_subscriptions/run_operation.sh" + ], + "exit": 0 + }, + { + "name": "adapter", + "command": [ + "bash", + "tests/ws_subscriptions/run_operation_adapter.sh" + ], + "exit": 0 + }, + { + "name": "control", + "command": [ + "bash", + "tests/ws_subscriptions/run_control.sh" + ], + "exit": 0 + }, + { + "name": "reviewer", + "command": [ + "bash", + "tests/ws_subscriptions/run_reviewer.sh" + ], + "exit": 0 + }, + { + "name": "f1_f2", + "command": [ + "bash", + "tests/ws_subscriptions/run_f1_f2.sh" + ], + "exit": 0 + }, + { + "name": "runtime", + "command": [ + "bash", + "tests/runtime/run_all.sh" + ], + "exit": 0 + }, + { + "name": "certificate", + "command": [ + "bash", + "tests/certificate/run_host.sh" + ], + "exit": 0 + }, + { + "name": "prompts", + "command": [ + "npm", + "test", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "name": "release", + "command": [ + "python3", + "tests/release/test_release.py" + ], + "exit": 0 + }, + { + "name": "shell_driver", + "command": [ + "bash", + "tests/ws_subscriptions/run_shell_driver.sh" + ], + "exit": 0 + }, + { + "name": "cross-node-en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs" + ], + "exit": 0 + }, + { + "name": "cross-node-zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ssh-poll-stack/results/host.log b/docs/repair/ssh-poll-stack/results/host.log new file mode 100644 index 0000000..88ff604 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/host.log @@ -0,0 +1,23 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ssh-poll-stack/results/operation.log b/docs/repair/ssh-poll-stack/results/operation.log new file mode 100644 index 0000000..b6d8772 --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/operation.log @@ -0,0 +1,2 @@ +PASS 16 failure schedules: encode/SDK/socket/stale peer, early/deferred done, duplicate tokens do not double-settle +PASS production operation/TX: 36 barrier schedules, ticket/target ledgers and B09 executor retention; destroyed=36 diff --git a/docs/repair/ssh-poll-stack/results/pre-push-adapter.log b/docs/repair/ssh-poll-stack/results/pre-push-adapter.log new file mode 100644 index 0000000..540987e --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/pre-push-adapter.log @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=94 diff --git a/docs/repair/ssh-poll-stack/results/prompts.log b/docs/repair/ssh-poll-stack/results/prompts.log new file mode 100644 index 0000000..0d43dee --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/prompts.log @@ -0,0 +1,53 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (15.478792ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (5.937417ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (7.435167ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (4.723791ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.639708ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.28575ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (6.398292ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (6.13025ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.63325ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.239875ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.615125ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.210291ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.657375ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (4.986208ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.557917ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.237416ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.676083ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.802ms) +✔ en-US: batch deletion all / partial / no success with business errors (6.061792ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.611833ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.258625ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (8.060875ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (5.021708ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (4.610625ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.513125ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.327458ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (5.266417ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (5.395334ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.610125ms) +✔ en-US: upload and download aggregates cover all success and all failure (4.95025ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (4.6015ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.356875ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.563125ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.351333ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.395417ms) +✔ en-US: unknown stop result never escalates to forced termination (4.2265ms) +✔ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (5.034334ms) +✔ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (4.587917ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.649333ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.097625ms) +ℹ tests 40 +ℹ suites 0 +ℹ pass 40 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 256.662875 diff --git a/docs/repair/ssh-poll-stack/results/release.log b/docs/repair/ssh-poll-stack/results/release.log new file mode 100644 index 0000000..e76e6ef --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/release.log @@ -0,0 +1,5 @@ +... +---------------------------------------------------------------------- +Ran 3 tests in 0.003s + +OK diff --git a/docs/repair/ssh-poll-stack/results/reviewer.log b/docs/repair/ssh-poll-stack/results/reviewer.log new file mode 100644 index 0000000..5a5cfbd --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/reviewer.log @@ -0,0 +1,15 @@ +PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds +PASS HTTPD barrier timeout retains worker and retry state +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ssh-poll-stack/results/runtime.log b/docs/repair/ssh-poll-stack/results/runtime.log new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/runtime.log @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ssh-poll-stack/results/shell_driver.log b/docs/repair/ssh-poll-stack/results/shell_driver.log new file mode 100644 index 0000000..b96e08c --- /dev/null +++ b/docs/repair/ssh-poll-stack/results/shell_driver.log @@ -0,0 +1,6 @@ +PASS real Shell+client: zero data is not EOF; EOF then close releases wrapper/channel/session/socket; close callback exactly once +PASS real Shell+client: fatal write/timeout retires channel; persistent close EAGAIN falls back to local session teardown without waiting +PASS real Shell+client: partial initialization/open/PTY/shell-start failure and bounded EAGAIN all release owned resources +PASS Shell run: local exit requested by input callback stops before another network read; close still owns cleanup +PASS actual WebUI cleanup twice uses cleared handles; original operation/ticket/target and actual lower resources drain +PASS real lower resources survive stop timeout; accepted output and terminal drain on retry with no new business message diff --git a/docs/repair/ssh-poll-stack/xterm.txt b/docs/repair/ssh-poll-stack/xterm.txt new file mode 100644 index 0000000..aa02cfa --- /dev/null +++ b/docs/repair/ssh-poll-stack/xterm.txt @@ -0,0 +1,16 @@ + +> test:xterm +> cd ../.. && node --test tests/prompts/xterm-vendor.test.cjs tests/prompts/xterm-offline.test.cjs + +✔ en-US: cold offline real xterm and terminal lifecycle (838.75975ms) +✔ zh-CN: cold offline real xterm and terminal lifecycle (734.621083ms) +✔ fixed vendor integrity, skip minify, gzip identity, local loader only (43.82125ms) +✔ production lazy loader: same-origin cold load, shared promise and retry (1.851333ms) +ℹ tests 4 +ℹ suites 0 +ℹ pass 4 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1755.460958 diff --git a/docs/repair/ws-control/README.md b/docs/repair/ws-control/README.md new file mode 100644 index 0000000..023ea0d --- /dev/null +++ b/docs/repair/ws-control/README.md @@ -0,0 +1,81 @@ +> 后续项目级契约修复与当前本地验收见 [v3 记录](../ws-project-v3/README.md)。本文件保留上一轮历史证据,不替代 v3 结论。 + +# PR #42:控制请求归属与业务取消统一修复 + +修改前基线为 `1591ecc8e293c0fa62feda18d2517edfc179ca5a`。实现阶段仅本地修改与验证;用户随后另行授权提交、推送并更新 PR #42,见 publication-gate.md。本轮没有改版本/发布流程或操作设备。既有 output/、tmp/、另一份未跟踪 reviewer diff-check 保留。 + +## 结论及修复范围 + +V1/V2 均在本轮修复前真实源码中复现业务断言失败,当前生产控制层与完整 WebSocket / Exec 调用路径通过相同行为断言。四种 Shell 页面控制共享完整 peer 校验及引用获取;Exec 取消意图与提交资格在同一操作锁内排序,并通过原操作绑定的 SSH `cancelled/cancel_context` 覆盖后续准备、连接和执行。 + +没有推翻 v2:原上下文、引用、编码前票据、逐目标结算、终态预留/封存、timer daemon 排空、遥测公平性和保护配额继续使用原结构。没有新增任务、队列、业务命令重试或永久保留旧上下文。 + +详见 [控制契约表](control-contract.md)。`changes.patch` 是本轮实际生产/测试增量,`changes.json` 记录对应文件哈希。 + +## 控制目标与所有权 + +- `ws_handler` 先以真实 req 的 sess_ctx 校验 transport 当前完整 peer,再把该 peer 传入唯一 `handle_ssh_control`。`shell_for_peer` 在原 op 锁内完成连接身份匹配、OPEN 检查及 ref++。后续输入、信号、resize 和断开只使用这一个 op;没有二次 current 查找。 +- 不匹配向原请求者返回既有 `ssh_status:error`,不操作其他 Shell。持引用后原会话若结束,资源 mutex 和 OPEN 检查阻止对已清理 shell 的访问;控制失败向请求者报错。输入/信号/resize 不自动重放。 +- disconnect 保存于原 context,由原 poller 执行,保持 disconnecting/closed 顺序。服务停止使用独立 `shell_owner`,连接关闭使用完整 peer 的 `shell_connection`;页面无法使用 owner 通配入口。 +- 补齐了同类旧关闭路径:原 `peer_closed -> cleanup_disconnected_client(fd)` 会查找并关闭复用 fd 的新连接。客户端登记现在保留完整 peer,关闭及清理都匹配原值,terminal takeover 也传递先前捕获的 peer,不从旧回调重新选择当前连接。 +- 页面控制只持短期 borrower 引用;网络/资源 I/O 在原资源 mutex 内,op 锁外。执行者、timer、票据及投递仍按 v2 各自归还责任。HTTPD 连接登记继续由既有 owner 管理,没有新增跨任务登记写入者。 + +## 持久取消与业务阶段 + +业务状态与网页观察阶段正交:PREPARING、SUBMITTED(表示已认领提交资格,不证明远端收到)、ENDED。原操作固定保存所有停止原因位和首个原因。 + +1. exact 非零 ID 的取消入口在同一 op 锁内校验已接受业务、尚未 ENDED、登记 USER 并取得原引用;不以 session 当前存在为接受条件。重复取消幂等,错误/旧 ID 和已结束任务拒绝。 +2. 配置的 `cancel_context` 指向原 op,session 只借用;执行者一直保活到断开并销毁 session。密钥加载前后观察意图;创建 session 时若发生取消,新 session 的配置继续读到它。连接/认证的底层协作检查使用同一 callback,不重置意图。 +3. `claim_submit` 和接受取消使用同一锁。取消先赢不能再获得资格;资格先赢后只能协作中止,可能已经执行,不能承诺从未提交或远端确定停止。这一保守边界在进入原 SSH exec 调用之前,不扩大锁到网络操作,也不重放命令。 +4. 业务返回/准备失败在锁内进入 ENDED 后才构造终态。后续取消拒绝,不修改封存结果;执行者、timer、投递可能仍在排空,所以 ENDED 与可回收不同。服务停止仍以依赖是否排空判断 busy/timeout。 +5. USER、TIMEOUT、MATCH 分开登记。先接受的原因决定取消解释,后续原因位仍保留。手动取消不会因驱动用 ESP_ERR_TIMEOUT 表示中止而被误报超时。MATCH 的首次提取停止不再因旧共享标记被误报超时;触发匹配、变量提取和 stop_on_match 的条件没有改变。原“已找到匹配时对 deadline 结果按匹配事实处理”的产品规则保留,不把匹配判断全部改成新策略。 +6. 观察/输出交付失败只封闭观察,不登记业务取消;此时业务仍可匹配、更新变量及接受明确的用户取消。服务停止也不登记 Exec 取消。已封存的观察失败不会被后来的业务取消重新改写或再发第二终态。 + +`ssh.cancel` 去掉先查 wildcard 状态再取消的旁路,直接 exact-ID 登记;用 valuedouble 校验完整 uint32 整数,避免高位 ID 被 valueint 截断。既有 `cancelled:true` 表示接受意图,协议字段不变。仅调整双语取消说明为远端终止未确认;前端布局和消息协议没有变化。 + +## 反例、测试与复现 + +设置 `IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf`、`DEVELOPER_DIR=/Library/Developer/CommandLineTools`。 + +| 命令 | 本轮结果与证据 | +|---|---| +| `python3 tests/ws_subscriptions/replay_control_baseline.py` | `baseline-results.txt`:V1/V2 都为业务断言 FAIL,脚本成功表示旧缺陷确认 | +| `bash tests/ws_subscriptions/run_control.sh v1` / `v2` | 当前完整生产路径对应断言 PASS;无参数执行下面全部交叉场景 | +| `bash tests/ws_subscriptions/run_control.sh` | `control-tests.txt`:WS 四入口、完整 peer/旧关闭/持引用、任务/密钥/创建/连接/认证/提交/业务封存阶段、原因、停止和 API | +| `bash tests/ws_subscriptions/run_operation.sh` | `operation-tests.txt`:票据、目标、引用和两阶段终态账本 | +| `bash tests/ws_subscriptions/run_operation_adapter.sh` | `adapter-tests.txt`:G1/G2、完整生产创建/回调/清理、观察失败仍执行业务、timer 排空/停止重试 | +| `bash tests/ws_subscriptions/run_host.sh` | `host-tests.txt`:TX、遥测、事件注销及上层生命周期 | +| `bash tests/ws_subscriptions/run_reviewer.sh` | `reviewer-tests.txt`:R1—R5 有效回归 | +| `bash tests/ws_subscriptions/run_f1_f2.sh` | `f1-f2-tests.txt`:流式失败、保护容量、资源不足和公平性 | +| `python3 tests/ws_subscriptions/replay_operation_baseline.py` | `historical-g1-g2.txt`:原完整冻结生产 G1/G2 仍可重放 | +| `bash tests/ws_subscriptions/run_f1_f2.sh --baseline` | `historical-f1-f2.txt`:旧 F1/F2 反例仍可重放 | +| `bash tests/runtime/run_all.sh` | `runtime-tests.txt`:含真实 SSH 驱动的六阶段 EAGAIN/deadline/cancellation;网络/libssh2 为边界替身 | +| `bash tests/certificate/run_host.sh` | `certificate-tests.txt`:证书/HTTPS 主机回归 | +| `npm --prefix tests/prompts test` | `webui-node-tests.txt`:38 项,含实际取消消息处理及中英文“远端终止未确认”断言 | +| `npm --prefix tests/prompts run test:browser` | `webui-browser-tests.txt`:Chrome 双语 38 项,后端模拟,不是设备联机 | +| 固定 SDK `idf.py -B /tmp/tianshan-control-build/build -D SDKCONFIG=/tmp/tianshan-control-build/sdkconfig build` | `build.txt`、`build-artifacts.json`:ESP32-S3 独立目录编译链接成功 | +| `git diff --check` | 通过,生产/测试修改;原始工具输出和冻结证据不做格式清洗 | + +新控制测试编译实际 controller、manager、TX 及整个 `ts_webui_ws.c`。`api_ssh_cancel` 从当前生产文件原样抽出编译,结果容器为边界替身;不是复制一套取消选择逻辑。网络边界注入确定性阶段屏障,真实底层 SSH 驱动另由 runtime 套件验证 callback 在握手、认证及执行等待中的持续检查;二者不能替代真实网络联机。 + +V1/V2 baseline.tar.gz 保存修改前真实生产源码和原测试;baseline.json 为逐文件哈希和 HEAD/status。baseline-adapter.c 仅替换 SDK/网络、观察输出和调度,baseline-control.c 含相同行为断言;原选择/取消逻辑未经替换。baseline-evidence.json 标识这些证据文件。首次重放因冻结目录缺少未改动的公共头而编译失败,补齐真实头后才得到业务红灯;没有将该编译失败算作缺陷证据。 + +回调/票据/投递/执行者账本继续由既有套件检查;新增交叉测试每场景最终要求 op 不忙、分配归零、timer 及 TX 排空。测试不依赖随机调度、sleep 或新业务消息来推进停止恢复。新增入口尚未接入 CI,本轮未改 CI。 + +## 资源与构建 + +目标编译器测量详见 resources.txt。op 槽由 928 B 增至 944 B,两个槽共增加 32 B;客户端登记由 20 B 增至 56 B,八个槽增加 288 B。相关静态总增 **320 B**(不含链接对齐)。Shell context 仍 20 B、Exec params 仍 792 B、输出票据仍 280 B;没有新动态对象、池或队列。 + +TX 仍 15 消息对象、96 描述符、1 MiB payload(保护独占 5 KiB),Shell/Exec 终态预留仍 4 KiB/512 KiB。控制 borrower 执行完释放;取消借用在登记及原资源 abort 请求后释放;配置 callback 的原上下文由原 executor/timer 保活至 session/timer 排空。没有额外任务或栈配置。 + +目标单函数帧:统一 Shell 控制 64 B,cancel/claim 各 32 B;Shell poller 2096 B、Exec callback 1088 B、Exec task 544 B。它们不是完整调用链峰值或实测栈水位。应用镜像 `0x214eb0`,最小应用分区剩余 `0xeb150`,约 31%。首次 SDK/Chrome 启动受沙箱限制,获得工具授权后本地完成;没有执行构建输出中的 flash 示例命令。 + +## 完整调用链自查与边界 + +1. **还有页面控制绕过统一目标获取吗?** 当前四个 Shell WS 控制均走同一入口;连接关闭走完整 peer,服务停止单独 owner。Exec API 直接 exact-ID 登记,没有用状态通配选择控制目标。 +2. **还有阶段会丢掉已接受取消吗?** 当前受测任务准备、密钥、session 创建、连接/认证、提交、执行均保存同一意图;业务 ENDED 后拒绝控制。同步密钥读取和 lwIP DNS 不可即时打断,但返回后仍观察同一取消,不会重新取得提交资格。 +3. **旧请求/回调还会查询当前操作并影响替换实例吗?** 页面控制取得引用后不重新查询;连接关闭不按旧 fd 查找新连接;Exec callback/timer 均持原上下文。保留的 wildcard 仅用于状态/服务维护:维护是对当前服务状态的主动请求,不是旧操作回调。 + +这些结论基于源码与确定性主机测试,不声称穷尽双核调度。仍需实机:真实慢连接及断网下 Shell 控制/重连、Exec 密钥/DNS/认证/提交时取消、远端实际是否终止、timer/结果排空与服务停止重试、连续启停后的堆/句柄及栈水位。 + +协议限制:Shell 帧无操作 ID,同一连接上的旧操作控制帧与该连接的新 Shell 无法区分;本轮只保证完整连接身份和已取得的原引用,不扩展协议。Exec cancel 沿用原 API 访问权限,不把 exact-ID 隔离等同新的用户授权机制。没有新增 ACK,传输结算不等于浏览器确认收到;取消被接受也不证明远端命令从未执行或已经终止。 diff --git a/docs/repair/ws-control/adapter-tests.txt b/docs/repair/ws-control/adapter-tests.txt new file mode 100644 index 0000000..7febc5e --- /dev/null +++ b/docs/repair/ws-control/adapter-tests.txt @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=84 diff --git a/docs/repair/ws-control/baseline-adapter.c b/docs/repair/ws-control/baseline-adapter.c new file mode 100644 index 0000000..0a26bb1 --- /dev/null +++ b/docs/repair/ws-control/baseline-adapter.c @@ -0,0 +1,287 @@ +/* Compile the entire production WS unit, its actual declarations/public types, + * controller, manager and TX. Only external platform/business boundaries fake. */ +#define main manager_regressions +#include "test_manager.c" +#undef main +#include "../../components/ts_webui/include/ts_webui.h" +#include "../../components/ts_core/ts_log/include/ts_log.h" +#undef TS_LOGD +#undef TS_LOGI +#undef TS_LOGW +#undef TS_LOGE +#define TS_LOGD(...) ((void)0) +#define TS_LOGI(...) ((void)0) +#define TS_LOGW(...) ((void)0) +#define TS_LOGE(...) ((void)0) +#include "ts_console.h" +#include "ts_ssh_client.h" +#include "ts_ssh_shell.h" +#include "ts_variable.h" +#define HTTP_GET 0 +#define HTTP_POST 1 +#define HTTP_PUT 2 +#define HTTP_DELETE 3 +#define HTTP_PATCH 4 +#include "ts_http_server.h" +#include "freertos/timers.h" +#include +#define HTTP_GET 0 +#define HTTPD_WS_TYPE_CLOSE 8 +#define CONFIG_TS_LOG_BUFFER_SIZE 16 +#define TS_EVENT_BASE_POWER "power" +#define TS_EVENT_ANY_ID -1 +typedef struct {const char *uri;int method;esp_err_t (*handler)(httpd_req_t *);void *user_ctx;bool is_websocket,handle_ws_control_frames;} httpd_uri_t; +static int httpd_register_uri_handler(httpd_handle_t h,const httpd_uri_t *u){(void)h;(void)u;return 0;} +static int httpd_ws_send_frame(httpd_req_t *r,httpd_ws_frame_t *f){return httpd_ws_send_frame_async(r->handle,r->fd,f);} +static const char *incoming; +static int httpd_ws_recv_frame(httpd_req_t *r,httpd_ws_frame_t *f,size_t n){(void)r;if(!incoming)return ESP_FAIL;f->type=1;f->len=strlen(incoming);if(n)memcpy(f->payload,incoming,f->len);return 0;} +static void *host_heap_malloc(size_t n,unsigned caps){(void)caps;return tracked_malloc(n);} +static void *host_calloc(size_t n,size_t z){void *p=tracked_malloc(n*z);if(p)memset(p,0,n*z);return p;} +static void *host_heap_calloc(size_t n,size_t z,unsigned caps){(void)caps;return host_calloc(n,z);} +static char *host_strdup(const char *s){size_t n=strlen(s)+1;char *p=tracked_malloc(n);if(p)memcpy(p,s,n);return p;} +static char *host_strndup(const char *s,size_t n){char *p=tracked_malloc(n+1);if(p){memcpy(p,s,n);p[n]=0;}return p;} +static struct {void (*fn)(void *);void *arg;} shell_task,exec_task; +static bool task_create_fail,close_during_create,inline_exec; +static int adapter_create(void(*fn)(void*),const char *name,unsigned stack,void *arg,unsigned priority,TaskHandle_t *out){ + (void)stack;(void)priority;(void)out;if(task_create_fail)return 0; + if(!strcmp(name,"ssh_poll"))shell_task=(typeof(shell_task)){fn,arg};else exec_task=(typeof(exec_task)){fn,arg}; + if(inline_exec && !strcmp(name,"ssh_exec"))fn(arg); + return pdPASS; +} +static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,void *arg,unsigned p,TaskHandle_t *out,unsigned caps); +#define malloc tracked_malloc +#define calloc host_calloc +#define free tracked_free +#define strdup host_strdup +#define strndup host_strndup +#define heap_caps_malloc host_heap_malloc +#define heap_caps_calloc host_heap_calloc +#define xTaskCreate adapter_create +#define xTaskCreateWithCaps adapter_create_caps +#include "ts_webui_ws.c" +#undef malloc +#undef calloc +#undef free +#undef strdup +#undef strndup +#undef heap_caps_malloc +#undef heap_caps_calloc +#undef xTaskCreate +#undef xTaskCreateWithCaps +struct ts_ssh_session_s {bool aborted;ts_ssh_config_t config;}; +static unsigned control_writes,control_signals,control_resizes,commands_submitted; +static void (*stage_hook)(const char *); +static void stage(const char *name){if(stage_hook)stage_hook(name);} +struct ts_ssh_shell_s {bool active;}; +static unsigned aborts,variable_writes,session_destroys; +static int remote_failure; +static void (*remote_hook)(void); +static bool remote_timeout; +static struct host_timer {void *id;void (*fn)(TimerHandle_t);bool active;} *host_timer; +static struct {void (*fn)(void *,uint32_t);void *arg;uint32_t value;TimerHandle_t deleted;} timer_queue[16]; +static unsigned timer_queued;static bool timer_queue_fail,timer_inline,timer_create_fail,timer_start_fail; +TimerHandle_t xTimerCreate(const char*n,TickType_t t,BaseType_t repeat,void*id,void(*fn)(TimerHandle_t)){ + (void)n;(void)t;(void)repeat;if(timer_create_fail)return NULL;host_timer=calloc(1,sizeof(*host_timer));host_timer->id=id;host_timer->fn=fn;return host_timer; +} +void *pvTimerGetTimerID(TimerHandle_t t){return t->id;} +BaseType_t xTimerStart(TimerHandle_t t,TickType_t wait){(void)wait;if(timer_start_fail)return pdFAIL;t->active=true;return pdPASS;} +BaseType_t xTimerDelete(TimerHandle_t t,TickType_t wait){(void)wait;if(timer_queue_fail)return pdFAIL;assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){.deleted=t};return pdPASS;} +BaseType_t xTimerPendFunctionCall(void(*fn)(void*,uint32_t),void *arg,uint32_t v,TickType_t wait){ + (void)wait;if(timer_queue_fail)return pdFAIL; + if(timer_inline && !timer_queued){fn(arg,v);return pdPASS;} + assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){fn,arg,v,NULL};return pdPASS; +} +static void timer_pump(void){while(timer_queued){typeof(timer_queue[0]) q=timer_queue[0];memmove(timer_queue,timer_queue+1,--timer_queued*sizeof(*timer_queue));if(q.deleted){free(q.deleted);host_timer=NULL;}else q.fn(q.arg,q.value);}} +esp_err_t ts_ssh_session_create(const ts_ssh_config_t*c,ts_ssh_session_t *out){stage("create");if(remote_failure==1)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));if(*out)(*out)->config=*c;return *out?ESP_OK:ESP_ERR_NO_MEM;} +esp_err_t ts_ssh_connect(ts_ssh_session_t s){stage("connect");if(s->config.cancelled && s->config.cancelled(s->config.cancel_context))return ESP_ERR_TIMEOUT;stage("auth");return remote_failure==2?ESP_FAIL:ESP_OK;} +const char *ts_ssh_get_error(ts_ssh_session_t s){(void)s;return "fake network error";} +esp_err_t ts_ssh_disconnect(ts_ssh_session_t s){(void)s;return ESP_OK;} +esp_err_t ts_ssh_session_destroy(ts_ssh_session_t s){session_destroys++;tracked_free(s);return ESP_OK;} +void ts_ssh_abort(ts_ssh_session_t s){s->aborted=true;aborts++;} +esp_err_t ts_ssh_shell_open(ts_ssh_session_t s,const ts_shell_config_t*c,ts_ssh_shell_t *out){(void)s;(void)c;if(remote_failure==3)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));(*out)->active=true;return 0;} +bool ts_ssh_shell_is_active(ts_ssh_shell_t s){return s&&s->active;} +esp_err_t ts_ssh_shell_close(ts_ssh_shell_t s){tracked_free(s);return 0;} +esp_err_t ts_ssh_shell_read(ts_ssh_shell_t s,char *b,size_t n,size_t *out){(void)b;(void)n;*out=0;s->active=false;return 0;} +esp_err_t ts_ssh_shell_write(ts_ssh_shell_t s,const char *b,size_t n,size_t *out){(void)s;(void)b;(void)n;(void)out;control_writes++;return 0;} +esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t s,uint16_t w,uint16_t h){(void)s;(void)w;(void)h;control_resizes++;return 0;} +esp_err_t ts_ssh_shell_send_signal(ts_ssh_shell_t s,const char *signal){(void)s;(void)signal;control_signals++;return 0;} +esp_err_t ts_ssh_exec_stream(ts_ssh_session_t s,const char *command,ts_ssh_output_cb_t cb,void *arg,int *code){ + (void)command;stage("submit");if(s->config.cancelled && s->config.cancelled(s->config.cancel_context))return ESP_ERR_TIMEOUT;commands_submitted++;if(remote_hook)remote_hook();if(remote_timeout && host_timer)host_timer->fn(host_timer); + cb("value=42\n",9,false,arg);*code=0;return s->aborted || (s->config.cancelled && s->config.cancelled(s->config.cancel_context))?ESP_ERR_TIMEOUT:ESP_OK; +} +esp_err_t ts_keystore_load_private_key(const char *id,char **out,size_t *n){(void)id;stage("key");*out=host_strdup("fake-key");*n=9;return ESP_OK;} +esp_err_t ts_variable_upsert(const ts_auto_variable_t *v){(void)v;variable_writes++;return 0;} +esp_err_t ts_console_exec(const char *cmd,ts_cmd_result_t *result){(void)cmd;memset(result,0,sizeof(*result));return 0;} +esp_err_t ts_console_clear_output_cb(void){return 0;} +esp_err_t ts_console_set_output_cb(ts_console_output_cb_t cb,void *arg){(void)cb;(void)arg;return 0;} +void ts_console_request_interrupt(void){} +esp_err_t ts_log_add_callback(ts_log_callback_t cb,ts_log_level_t l,void *arg,ts_log_callback_handle_t *out){(void)cb;(void)l;(void)arg;*out=(void*)1;return 0;} +static int remove_log_result; +esp_err_t ts_log_remove_callback(ts_log_callback_handle_t h){(void)h;return remove_log_result;} +size_t ts_log_buffer_search(ts_log_entry_t *e,size_t n,ts_log_level_t min,ts_log_level_t max,const char *tag,const char *keyword){(void)e;(void)n;(void)min;(void)max;(void)tag;(void)keyword;return 0;} +httpd_handle_t ts_http_server_get_handle(void){return (void*)11;} +void ts_http_server_set_stop_hooks(esp_err_t(*stop)(httpd_handle_t),void(*stopped)(httpd_handle_t)){(void)stop;(void)stopped;} +static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){(void)caps;if(close_during_create)((ssh_shell_context_t*)arg)->shell->active=false;return adapter_create(fn,n,stack,arg,p,out);} +static void drive_all(void){for(unsigned i=0;i<12;i++){ts_ws_op_poll();pump();timer_pump();}assert(!timer_queued);} +static void setup(void){start();memset(s_clients,0,sizeof(s_clients));s_server=(void*)11;s_ws_stopping=false;ts_ws_op_enable();transport_server.closed=peer_closed;for(int fd=1;fd<=2;fd++){reqs[fd]=(httpd_req_t){.handle=(void*)11,.fd=fd};current=(void*)3;assert(add_client(&reqs[fd],WS_CLIENT_TYPE_EVENT)==ESP_OK);}current=(void*)1;} +static void finish_all(void){drive_all();assert(!ts_ws_op_busy());stop();assert(!live_allocations);} +static void connect_shell(void){cJSON *j=cJSON_Parse("{\"host\":\"fake\",\"user\":\"fake\"}");current=(void*)3;handle_ssh_connect(&reqs[1],j);current=(void*)1;cJSON_Delete(j);} +static unsigned terminal_frames,output_frames,connected_frames,disconnecting_frames;static bool output_after_terminal; +static void observe(httpd_ws_frame_t *f){const char *p=(char*)f->payload;if(strstr(p,"ssh_output")||strstr(p,"ssh_exec_output")){if(terminal_frames)output_after_terminal=true;output_frames++;}if(strstr(p,"ssh_exec_done")||strstr(p,"ssh_exec_error")||strstr(p,"\"status\":\"error\"")||strstr(p,"\"status\":\"closed\""))terminal_frames++;if(strstr(p,"\"status\":\"connected\""))connected_frames++;if(strstr(p,"\"status\":\"disconnecting\""))disconnecting_frames++;} +static jmp_buf worker_yield; +static void yield_worker(void){longjmp(worker_yield,1);} +static void worker_step(void){wait_hook=yield_worker;current=(void*)2;if(!setjmp(worker_yield))worker_fn(NULL);current=(void*)1;wait_hook=NULL;} +static void sdk_one(void){if(!queued)return;current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(*queue));q.fn(q.arg);current=(void*)1;} +static void progress(void){sdk_one();if(s_worker){if(s_state==STOPPING)worker_exit();else worker_step();}timer_pump();} +static void finish_ws(void){drive_all();delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL;for(int i=0;i<32;i++)if(reqs[i].sess_ctx)close_peer(i);ts_webui_ws_stopped((void*)11);assert(!live_allocations);} +static uint32_t paused_id; +static void g1_original_callback(void){ + close_peer(1); /* HTTPD retires the old target while worker callback is paused */ + shell_task.fn(shell_task.arg); /* independent poller exits */ + drive_all();open_peer(1);connect_shell(); + ts_ws_op_stats_t state;ts_ws_op_stats(TS_WS_OP_SHELL,&state); + assert(state.identity==paused_id && state.phase!=OP_FREE && state.refs); +} +static void g2_preparing_output(void){ + sdk_one();queue_fail=true;worker_step();queue_fail=false;test_now+=100000; + drive_all();ts_ws_op_stats_t state;ts_ws_op_stats(TS_WS_OP_EXEC,&state); + assert(state.phase==OP_CLOSING && state.preparing==1 && !state.finalizers); +} +static void fail_observation_business_continues(void){ + ssh_exec_task_params_t *params=exec_task.arg; + drive_all();queue_fail=true;ssh_exec_output_callback("before",6,false,params);queue_fail=false;test_now+=100000;drive_all(); + assert(!ts_ws_op_is_open(params->op) && ts_webui_ssh_exec_is_running(params->session_id)); +} +static void close_snapshot_joiner(void){open_peer(3);ts_ws_op_poll();} +static void cancel_original_exec(void){ssh_exec_task_params_t *params=exec_task.arg;assert(ts_webui_ssh_exec_cancel(0)==ESP_ERR_INVALID_STATE);assert(ts_webui_ssh_exec_cancel(params->session_id)==ESP_OK);} +static void validate_exec_frame(httpd_ws_frame_t *f){ + const char *p=(char*)f->payload; + assert(strstr(p,"\"type\":") && strstr(p,"\"session_id\":")); + if(strstr(p,"ssh_exec_output"))assert(strstr(p,"\"data\":")); + if(strstr(p,"ssh_exec_error"))assert(strstr(p,"\"error\":")); +} +static void stop_progress_shell(void){ + if(shell_task.fn && !ts_ws_op_starting(((ssh_shell_context_t*)shell_task.arg)->op)){ + void (*fn)(void*)=shell_task.fn;void *arg=shell_task.arg;shell_task.fn=NULL;fn(arg); + } + progress(); +} +static void operation_cross_tests(void){ + uint32_t id;ts_ws_op_stats_t ledger; + setup();connect_shell();unsigned dc=disconnecting_frames;handle_ssh_disconnect();shell_task.fn(shell_task.arg);finish_all();assert(disconnecting_frames==dc+1); + setup();terminal_frames=output_frames=0;output_after_terminal=false;connect_shell(); + ssh_shell_context_t *ctx=shell_task.arg;paused_id=ts_ws_op_id(ctx->op); + ts_ws_message_t *m=ts_ws_message_text("block",5); + assert(ts_ws_transport_submit(ts_ws_op_peer(ctx->op),m,0,0,NULL,NULL)==0);ts_ws_message_release(m); + ssh_send_output(ctx,"old",3); /* original producer returns before async rejection */ + sdk_one();barrier_name="B06";barrier_action=g1_original_callback;queue_fail=true;worker_step(); + queue_fail=false;test_now+=100000;assert(!barrier_action);drive_all();connect_shell();ctx=shell_task.arg; + assert(ts_ws_op_id(ctx->op)>paused_id && ts_ws_op_is_open(ctx->op));ssh_cleanup();shell_task.fn(shell_task.arg);finish_all(); + puts("PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit)"); + + setup();terminal_frames=output_frames=0;output_after_terminal=false; + assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); + ssh_exec_task_params_t *params=exec_task.arg;ts_ws_peer_t peer=*(ts_ws_peer_t*)reqs[1].sess_ctx; + m=ts_ws_message_text("block",5);assert(ts_ws_transport_submit(peer,m,0,0,NULL,NULL)==0);ts_ws_message_release(m); + ssh_exec_output_callback("A",1,false,params);barrier_name="B02";barrier_action=g2_preparing_output; + ssh_exec_output_callback("B",1,false,params);drive_all();assert(!barrier_action && !output_after_terminal && terminal_frames==2); + exec_task.fn(exec_task.arg);finish_all(); + puts("PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal"); + + setup();terminal_frames=0;ts_webui_ssh_options_t opts={.timeout_ms=1000,.collect_output=true,.extract_pattern="value=(.*)",.var_name="fake"}; + assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + timer_queue_fail=true;exec_task.fn(exec_task.arg);drive_all();assert(ts_ws_op_busy()); + params=exec_task.arg;assert(params->timer_phase==2 && !params->session); + /* A late original timer callback cannot touch freed resources or a new task. */ + unsigned before=aborts;host_timer->fn(host_timer);assert(aborts==before); + delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);delay_hook=NULL; + timer_queue_fail=false;for(unsigned i=0;i<20;i++){test_now+=100000;progress();} + assert(!ts_ws_op_busy());finish_ws(); + puts("PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement"); + + setup();assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + timer_queue_fail=true;exec_task.fn(exec_task.arg); + for(unsigned i=0;itimer_phase==6);timer_queue_fail=false; + delay_hook=progress;esp_err_t stopped=ts_webui_ws_stop((void*)11);delay_hook=NULL; + assert(stopped==ESP_OK || stopped==ESP_ERR_TIMEOUT); + for(unsigned i=0;i<20;i++){test_now+=100000;progress();}assert(!ts_ws_op_busy());finish_ws(); + puts("PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry"); + + setup();remote_hook=fail_observation_business_continues;unsigned writes=variable_writes; + assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);remote_hook=NULL;assert(variable_writes>writes && !aborts);finish_all(); + puts("PASS B09 observation failure still executes actual matching and variable updates without aborting remote command"); + + setup();remote_timeout=true;before=aborts; + assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);remote_timeout=false;assert(aborts==before+1);finish_all(); + setup();opts.stop_on_match=true;before=aborts; + assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);assert(aborts==before+1);finish_all(); + puts("PASS original timeout and stop-on-match business abort semantics retained"); + + setup();before=aborts;remote_hook=cancel_original_exec; + assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); + exec_task.fn(exec_task.arg);remote_hook=NULL;assert(aborts==before+1);finish_all(); + setup();terminal_frames=0; + assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); + params=exec_task.arg;barrier_name="B07";barrier_action=close_snapshot_joiner; + if(ts_ws_op_close_begin(params->op))ts_ws_op_close_finish(params->op,"{\"type\":\"ssh_exec_done\"}"); + drive_all();assert(!barrier_action && frames[3]==0 && terminal_frames==2); + exec_task.fn(exec_task.arg);finish_all(); + puts("PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot"); + + setup();close_peer(1);close_peer(2); + assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); + params=exec_task.arg;before=allocations;ssh_exec_output_callback("none",4,false,params);assert(allocations==before); + exec_task.fn(exec_task.arg);finish_all(); + puts("PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire"); + + setup();task_create_fail=true;assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==ESP_FAIL);task_create_fail=false;finish_all(); + for(unsigned i=0;i<16;i++) { + setup();fail_allocation=allocations+i+1; + esp_err_t ret=ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id);fail_allocation=0; + if(ret==ESP_OK)exec_task.fn(exec_task.arg);finish_all(); + } + puts("PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed"); + for(unsigned i=0;i<48;i++) { + setup();assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); + sent_hook=validate_exec_frame;params=exec_task.arg;fail_allocation=allocations+i+1; + ssh_exec_output_callback("encoding",8,false,params);fail_allocation=0; + exec_task.fn(exec_task.arg);finish_all(); + } + sent_hook=observe; + puts("PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain"); + setup();connect_shell();current=(void*)2;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);current=(void*)1; + delay_hook=stop_progress_shell;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL;finish_ws(); + setup();assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);ts_ws_op_poll();timer_pump();timer_inline=true;ts_ws_op_poll();timer_inline=false;finish_all(); + puts("PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned"); + for(unsigned mode=0;mode<2;mode++) { + setup();timer_create_fail=mode==0;timer_start_fail=mode==1; + assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);timer_create_fail=timer_start_fail=false;finish_all(); + } + puts("PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged"); + (void)ledger; +} +#ifndef OP_ADAPTER_NO_MAIN +int main(void){ + cJSON_Hooks h={tracked_malloc,tracked_free};cJSON_InitHooks(&h);sent_hook=observe; + setup();connect_shell();assert(shell_task.fn && connected_frames==1); + ssh_shell_context_t *ctx=shell_task.arg;queue_fail=true;ssh_send_output(ctx,"out",3);queue_fail=false;test_now+=100000;drive_all();assert(terminal_frames==1);shell_task.fn(shell_task.arg);finish_all(); + setup();terminal_frames=0;output_after_terminal=false;connect_shell();ctx=shell_task.arg; + ssh_send_output(ctx,"out",3);ssh_cleanup();shell_task.fn(shell_task.arg);finish_all();assert(!output_after_terminal); + for(int f=0;f<5;f++){setup();terminal_frames=0;unsigned before=connected_frames;task_create_fail=f==0;close_during_create=f==1;remote_failure=f>=2?f-1:0;shell_task.fn=NULL;connect_shell();if(shell_task.fn)shell_task.fn(shell_task.arg);finish_all();assert(connected_frames==before);task_create_fail=close_during_create=false;remote_failure=0;} + setup();terminal_frames=0;output_after_terminal=false;uint32_t id; + ts_webui_ssh_options_t opts={.collect_output=true,.timeout_ms=1000,.extract_pattern="value=(.*)",.var_name="fake"}; + assert(ts_webui_ssh_exec_start_ex("fake",22,"user",NULL,"password","cmd",&opts,&id)==0); + exec_task.fn(exec_task.arg);drive_all();assert(terminal_frames==2 && !output_after_terminal && variable_writes);finish_all(); + setup();inline_exec=true;assert(ts_webui_ssh_exec_start("fake",22,"user",NULL,"password","cmd",&id)==0);inline_exec=false;finish_all(); + operation_cross_tests(); + printf("PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=%u\n",session_destroys); + return 0; +} + +#endif diff --git a/docs/repair/ws-control/baseline-control.c b/docs/repair/ws-control/baseline-control.c new file mode 100644 index 0000000..3d9d20d --- /dev/null +++ b/docs/repair/ws-control/baseline-control.c @@ -0,0 +1,20 @@ +#define OP_ADAPTER_NO_MAIN +#include "test_operation_adapter.c" +static void dispatch(unsigned fd,const char *text){incoming=text;reqs[fd].method=1;current=(void*)3;assert(ws_handler(&reqs[fd])==ESP_OK);current=(void*)1;incoming=NULL;} +static void shell_on(unsigned fd){cJSON *j=cJSON_Parse("{\"host\":\"fake\",\"user\":\"fake\"}");current=(void*)3;handle_ssh_connect(&reqs[fd],j);current=(void*)1;cJSON_Delete(j);} +static bool ownership_case(void){ + setup();connect_shell();ssh_cleanup();shell_task.fn(shell_task.arg);drive_all();shell_on(2); + unsigned w=control_writes,s=control_signals,r=control_resizes; + dispatch(1,"{\"type\":\"ssh_input\",\"data\":\"bad\"}");dispatch(1,"{\"type\":\"ssh_signal\",\"signal\":\"INT\"}");dispatch(1,"{\"type\":\"ssh_resize\",\"width\":90,\"height\":30}");dispatch(1,"{\"type\":\"ssh_disconnect\"}"); + bool ok=control_writes==w && control_signals==s && control_resizes==r && !((ssh_shell_context_t*)shell_task.arg)->disconnect_requested; + ssh_cleanup();shell_task.fn(shell_task.arg);finish_all();return ok; +} +static bool early_cancel_case(void){ + setup();uint32_t id;assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); + unsigned before=commands_submitted;assert(ts_webui_ssh_exec_cancel(id)==ESP_OK);exec_task.fn(exec_task.arg);finish_all();return commands_submitted==before; +} +int main(int argc,char **argv){ + cJSON_Hooks h={tracked_malloc,tracked_free};cJSON_InitHooks(&h);sent_hook=observe; + if(argc==2){bool ok=!strcmp(argv[1],"v1")?ownership_case():early_cancel_case();printf("%s business_contract=%s\n",argv[1],ok?"PASS":"FAIL");return ok?0:1;} + assert(ownership_case());assert(early_cancel_case());puts("PASS actual WS ownership and accepted pre-task cancellation");return 0; +} diff --git a/docs/repair/ws-control/baseline-evidence.json b/docs/repair/ws-control/baseline-evidence.json new file mode 100644 index 0000000..3451ea2 --- /dev/null +++ b/docs/repair/ws-control/baseline-evidence.json @@ -0,0 +1,6 @@ +{ + "baseline.tar.gz": "3803b43c97c169dc726cdf0dc4af71f1983b45888c2f9583ef15a7f3b719185d", + "baseline.json": "ad715c9929badd471a04aa02ab8fb9bfe89f07bc82c9cf9453265fbf5a9bc162", + "baseline-adapter.c": "f8150e4d145b2e6834b3017b2ee1be2814fd987e7771e96a7c7e2c275c0c90ac", + "baseline-control.c": "bad7173f8006aa42ad8977112f2914d055000ad166b019659ba1c579762488b9" +} diff --git a/docs/repair/ws-control/baseline-results.txt b/docs/repair/ws-control/baseline-results.txt new file mode 100644 index 0000000..46ac40c --- /dev/null +++ b/docs/repair/ws-control/baseline-results.txt @@ -0,0 +1,3 @@ +v1 business_contract=FAIL +v2 business_contract=FAIL +CONFIRMED: both failures are production business assertions; complete frozen source hashes verified diff --git a/docs/repair/ws-control/baseline.json b/docs/repair/ws-control/baseline.json new file mode 100644 index 0000000..f2f60f5 --- /dev/null +++ b/docs/repair/ws-control/baseline.json @@ -0,0 +1,81 @@ +{ + "HEAD": "1591ecc8e293c0fa62feda18d2517edfc179ca5a", + "status": "?? docs/repair/ws-control/\n?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt\n?? output/\n?? tmp/\n", + "sha256": { + "components/ts_webui/CMakeLists.txt": "53e02258893758d55edf0debef2e0694b154ecccda65ab3b5bb5d34770c39d45", + "components/ts_webui/Kconfig": "6a1fc77d34f7c635b44a922f4c7c9fb96832a9f6bb433967c26e3bdc451ae286", + "components/ts_webui/web/favicon.ico": "1ea04b690d7fe816da5efb405c13f9cd953366026eb3553e214de8d5df0d3648", + "components/ts_webui/web/index.html": "0b3ce77c7da2da7d18bd086dfe55fc33e994adbfe06f2f47eb6d69c01fe6124a", + "components/ts_webui/include/ts_ws_subscriptions.h": "edcfedcdb48cc47bdd776218d43f362f4f2feb84f0a8bd347b465e3dd751e3ae", + "components/ts_webui/include/ts_ws_transport.h": "4c7b996ed4e6a578ce7daa1a02a13729795bd4dca2e66eb8b49895b6f59f36ee", + "components/ts_webui/include/ts_ws_operation.h": "1c57f95fed42db3a478e73755c047b0ab64fe68b5dd3e64d0e6a7a673b6c8c11", + "components/ts_webui/include/ts_webui.h": "374e230b4f0d016adb2373acd2e6431cf537eaeb8f7f84efcf53523d6dad0402", + "components/ts_webui/src/ts_webui_ws.c": "ff9eb33748bf3c33a3df99273ec634512e74ca2207b610a8e4ee0791cdb56122", + "components/ts_webui/src/ts_ws_transport.c": "e2eaeb31d00d7996a84badc669ca5587628c63b044c9a8014e587e84b5ab37f8", + "components/ts_webui/src/ts_ws_operation.c": "db6fa86b5759079e4477cdd9e1239bc1fc2d50c4b59cd007f9886638ce848097", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_api.c": "c8225f3fc36be3446947e205932a3d43340665d687b81c23c16556f3be8dc9b8", + "components/ts_webui/src/ts_ws_subscriptions.c": "9f8d2f33a374d6992a1ef119cd20a791244e44abc8d7cd66dc906b4896f764fb", + "components/ts_webui/web/css/style.css": "30dab8799ed2a8b0a5da49ec84202b30f3c951779ea4533e847a53b2ac9b8dff", + "components/ts_webui/web/images/tslogo-32.png": "64e4bce72f2b13c81bef5b46ae919abeeb47f98571cf5e55460385880731810b", + "components/ts_webui/web/images/tslogo-512.png": "b7508585c46e16fcc7d42c52459ab55df32716aea85a10a560cd64de7cceb8e8", + "components/ts_webui/web/images/tslogo-128.png": "f09ac97789726872277a0399338cd9bfd0493752de930aeb6b2c6f7b0a864c3b", + "components/ts_webui/web/images/README.md": "f4429665c315cdabc2a935caf0f1423632dd7cbff84f34914965969217102237", + "components/ts_webui/web/images/tslogo-48.png": "41f959e327dca63386a2f254b8a245a6fa151904a06eae93ae6c449277467f70", + "components/ts_webui/web/images/tslogo-256.png": "55dc7df59429c23fdc531baba002b7b23f5a4f2be0f29b2ecc5098f3df059da7", + "components/ts_webui/web/images/tslogo-64.png": "a0809405c5632eb4bf1f1b4783175c2b92b25fc522f5b0682a35d3cfa1c58752", + "components/ts_webui/web/images/favicon.icns": "bdc873fa7bff5e1888d80273f99f22d97d3719d4b17419e68e64eafd85c2b039", + "components/ts_webui/web/images/tslogo-original.png": "9fb0ee8532c2d572d8b235f7586d225f00609cf8defb98b59cf55ae749e83ed1", + "components/ts_webui/web/js/terminal.js": "048ca0d64b9ee52b0c2b4f3f3f7e270a2bbd35fc729dbd513cc7b11dfb26bbcf", + "components/ts_webui/web/js/router.js": "1e73ca3bf272a54aea8c516809e09e10f257b620bf66311bbbe358693fe377d5", + "components/ts_webui/web/js/dragSort.js": "7c5b9159cb8bb88b35222424db6d8bd822d3960899d5c090c17955700d6590af", + "components/ts_webui/web/js/api.js": "6fb266abb3780a0d402d86ad95a3644b8e1f488136ad44dc18ddd83caaa8dab4", + "components/ts_webui/web/js/i18n.js": "2eed1c54b4ef89bc2e4221a3fd900e88bd8d7a11064a04d97dcc3decfdeedbd8", + "components/ts_webui/web/js/app.js": "ad63a38112eab45af87da091f3536156614db526bb85f2c83bafa7867439230b", + "components/ts_webui/web/fonts/remixicon.woff2": "e92dc38bfb1d15dbb9d9ca9e645754f68e7c5b224e33c45a17048bd0cf2407a6", + "components/ts_webui/web/fonts/remixicon.css": "b2218eec4e02513f0feef46f74f13c852152f54eafd83d1274057e3895f0ea1c", + "components/ts_webui/web/js/lang/en-US.js": "70e02d67c772b659e5233356938c8344f1caf740ece2f6c3bbdc1c0a1e3c6f72", + "components/ts_webui/web/js/lang/zh-CN.js": "32ee2006259183f7ef03a98532e39a2a75b39c9ed9ab9680fa6279e90d9ea0af", + "tests/ws_subscriptions/test_init.c": "49b7ade237c4fe5df5fe683f4ec731c222cc4939b91b19d976471e99d29173c7", + "tests/ws_subscriptions/test_operation.c": "c28fd00d191f92bbe8722033a3dbf5d7c6bcc54e054c06acff4429fce149a4e6", + "tests/ws_subscriptions/run_reviewer.sh": "2a957bb5d4e0ca0c357ec32fffb23aa60c75019b60cc4c5c33d468d389013ea8", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/test_manager.c": "a1b46f3ad3a877a5cfd1235e7253418aec965c442a5c21ab811a68f1e70be8cd", + "tests/ws_subscriptions/test_f1_f2.c": "7d4907e42f3a9c7110055acb6ca667abd62a5f16712306c7dde6b85ec285c9b4", + "tests/ws_subscriptions/test_reviewer.c": "65916f6af7fb3fe00d00bf6999a55f441422b35d4d95b3f801d9cb9b0f591c54", + "tests/ws_subscriptions/test_reviewer_service.c": "3fa82db0882b90d69450ddcd7a50e5904ae60e2cab8e62ea11656ac4c21e2890", + "tests/ws_subscriptions/README.md": "e2a186d0cc38c5a2df86207cde9f371365b95e678908b15943a7556fe57e5ada", + "tests/ws_subscriptions/test_operation_adapter.c": "832ffe800b228b453d920e75e6d2070d0b45db6217c3edab9535d3f0903873f7", + "tests/ws_subscriptions/run_operation_adapter.sh": "1a5b900b4c6aae1619b86a285b6371a683263304db90a81d82477d8fb750d3f5", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/run_reviewer_baseline.sh": "6ea73543f64c6de65f59480300cf2d73ece85b798a7a430df5b55f2adae1bb96", + "tests/ws_subscriptions/replay_operation_baseline.py": "ba26a739d9dfb4b30b4e10ac0b3955994738820b85a156406dcaaa9518382cc3", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_reviewer_core.c": "7669567ad82171ae32102779e4fc98c4b88871f9e9f761600a21623378882ef2", + "tests/ws_subscriptions/run_operation.sh": "bf9d6db03b483d4b74db26e464efc73b673648ef82565edf987e6f275c9ee6c5", + "tests/ws_subscriptions/run_f1_f2.sh": "8e804b7a5c66663a62da53f9027b175722034e5cce77ba152aba8ad13b527935", + "tests/ws_subscriptions/test_reviewer_http.c": "2b9696ac9dd86be96db383392d3bcf61f81a5ab2e881933d767aad8f91d30c00", + "tests/ws_subscriptions/baseline_operation_adapter.c": "0b0703b144fa8fc7d412110e55b4d7d2010196e9422deb78ff00185059a5af05", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_console.h": "f97fca9ebf2a497277d9ac5af3581a2e83789b4acf3e8b125e0f36fb27210151", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "de005401b26f9dce9028db4bbc656ea72e55730535769be4ddf31ccec072c2dc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/timers.h": "fd6abec4a547b6e9caed8f0514a08ead4223303736dade89179bb8812a2a5d94", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "components/ts_security/src/ts_ssh_client.c": "071b875b4029cc9d0d9e5538ce7a05921a07ec57d09faa45d295fccb7625552d", + "components/ts_security/include/ts_ssh_client.h": "ceb00ed29965279a154e061638b58769e148ea370f5435de48c90c1c8d90f928", + "components/ts_api/src/ts_api_ssh.c": "b3e9c84fe578516e506b5cdbf9a4e7ebfab4094558ea908e52d70c6de9339bc4" + } +} diff --git a/docs/repair/ws-control/baseline.tar.gz b/docs/repair/ws-control/baseline.tar.gz new file mode 100644 index 0000000..8acb7af Binary files /dev/null and b/docs/repair/ws-control/baseline.tar.gz differ diff --git a/docs/repair/ws-control/build-artifacts.json b/docs/repair/ws-control/build-artifacts.json new file mode 100644 index 0000000..65e6bc0 --- /dev/null +++ b/docs/repair/ws-control/build-artifacts.json @@ -0,0 +1,10 @@ +{ + "sdk": "ESP-IDF v5.5.2", + "target": "ESP32-S3", + "directory": "/tmp/tianshan-control-build/build", + "sha256": { + "/tmp/tianshan-control-build/build/TianShanOS.bin": "d1d2e2bb77bb55fa26f86a5ca5b26177d63cb30f5f6c21e342f9364eed73acec", + "/tmp/tianshan-control-build/build/www.bin": "375affb87ac595088afa21c5b93dae736a449b56d12d2a080504ed331251e81b", + "/tmp/tianshan-control-build/sdkconfig": "1340e033b5865e39dd6b8c3516dffb27d01da5aff41127c69b583cbfb99acef0" + } +} diff --git a/docs/repair/ws-control/build.txt b/docs/repair/ws-control/build.txt new file mode 100644 index 0000000..bb6c447 --- /dev/null +++ b/docs/repair/ws-control/build.txt @@ -0,0 +1,30 @@ +Executing action: all (aliases: build) +Running ninja in directory /private/tmp/tianshan-control-build/build +Executing "ninja all"... +[1/10] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-control-build/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-control-build/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[2/10] No install step for 'bootloader' +[3/10] cd /tmp/tianshan-control-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-control-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-control-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[4/10] Completed 'bootloader' +[5/10] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[6/10] Linking C static library esp-idf/ts_webui/libts_webui.a +[7/10] Generating esp-idf/esp_system/ld/sections.ld +[8/10] Linking CXX executable TianShanOS.elf +[9/10] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-control-build/build/TianShanOS.bin +[10/10] cd /tmp/tianshan-control-build/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-control-build/build/partition_table/partition-table.bin /tmp/tianshan-control-build/build/TianShanOS.bin +TianShanOS.bin binary size 0x214eb0 bytes. Smallest app partition is 0x300000 bytes. 0xeb150 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-control-build/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-control-build/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-control-build/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-control-build/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-control-build/build/www.bin +or from the "/private/tmp/tianshan-control-build/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ws-control/certificate-tests.txt b/docs/repair/ws-control/certificate-tests.txt new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ws-control/certificate-tests.txt @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ws-control/changes.json b/docs/repair/ws-control/changes.json new file mode 100644 index 0000000..4d140c5 --- /dev/null +++ b/docs/repair/ws-control/changes.json @@ -0,0 +1,18 @@ +{ + "HEAD": "1591ecc8e293c0fa62feda18d2517edfc179ca5a", + "scope": "local only, no commit/push/PR/device operations", + "source_and_test_sha256": { + "components/ts_api/src/ts_api_ssh.c": "edbf7f6a4c80f3b15a75e7b39096ca0e6fe6c98ab1cc5c3e3091b5c947646ff7", + "components/ts_webui/include/ts_ws_operation.h": "4a31681f9e5d0041d2627b5850b23c083e1b0ca3b876acf959adab5955611512", + "components/ts_webui/src/ts_webui_ws.c": "8f26c8ddf9bf391a70ec0909809e2a084352f4cff23c97875baecd838e4eb4ba", + "components/ts_webui/src/ts_ws_operation.c": "504ce5caa9375a792692eec681a86bf4515aa5c2d28e758d67df08117b6fe865", + "components/ts_webui/web/js/lang/en-US.js": "24bfe60afe5589d5f257baa6b1ef66f23e23453f70be9c8bd7778944f73ac3fc", + "components/ts_webui/web/js/lang/zh-CN.js": "0ec109e51f3bc21531f8fca829eaed271898a4cfd7172696881013d5b20e6817", + "tests/prompts/regression.test.cjs": "c372b74e125b361103defe66017c3eeb286fea9975cf4f3167ed5cf981050516", + "tests/ws_subscriptions/test_operation_adapter.c": "4178c7dd1b9ad582cdc0fd5950dced82d448494494702dfd30246d7ba60f3338", + "tests/ws_subscriptions/test_control.c": "7e70ad841a86f6c39a1274f715502991e37c7aa1b7802f7b3dcf805a6aa7d917", + "tests/ws_subscriptions/run_control.sh": "e2853acc8652b99dfccca85d25425b870996e7bfcb03a5cfe021b76e66d0139e", + "tests/ws_subscriptions/replay_control_baseline.py": "aefd5ff8bc6ced036c9fec466bef70bddb8b66949b4eed3994cdd109fe2f255f" + }, + "patch_sha256": "00258dc9ae34c33ae25df12c1caa9d8f53684aade3e25bc07c114e225f4544e5" +} diff --git a/docs/repair/ws-control/changes.patch b/docs/repair/ws-control/changes.patch new file mode 100644 index 0000000..4842c9a --- /dev/null +++ b/docs/repair/ws-control/changes.patch @@ -0,0 +1,862 @@ +diff --git a/components/ts_api/src/ts_api_ssh.c b/components/ts_api/src/ts_api_ssh.c +index 95360d3..5d6ef53 100644 +--- a/components/ts_api/src/ts_api_ssh.c ++++ b/components/ts_api/src/ts_api_ssh.c +@@ -545,24 +545,19 @@ static esp_err_t api_ssh_cancel(const cJSON *params, ts_api_result_t *result) + { + const cJSON *sid = cJSON_GetObjectItem(params, "session_id"); + +- uint32_t session_id = 0; +- if (sid && cJSON_IsNumber(sid)) { +- session_id = (uint32_t)sid->valueint; +- } +- +- /* 检查会话是否在运行 */ +- if (!ts_webui_ssh_exec_is_running(session_id)) { ++ /* Exact instance identity; a status wildcard is never a control target. */ ++ if (!cJSON_IsNumber(sid) || sid->valuedouble < 1 || sid->valuedouble > UINT32_MAX || ++ sid->valuedouble != (double)(uint32_t)sid->valuedouble) { + ts_api_result_error(result, TS_API_ERR_NOT_FOUND, "No running session"); + return ESP_ERR_NOT_FOUND; + } +- +- /* 取消执行 */ +- esp_err_t ret = ts_webui_ssh_exec_cancel(session_id); ++ esp_err_t ret = ts_webui_ssh_exec_cancel((uint32_t)sid->valuedouble); + if (ret != ESP_OK) { +- ts_api_result_error(result, TS_API_ERR_INTERNAL, "Failed to cancel"); ++ ts_api_result_error(result, ret == ESP_ERR_INVALID_STATE ? TS_API_ERR_NOT_FOUND : TS_API_ERR_INTERNAL, ++ ret == ESP_ERR_INVALID_STATE ? "No running session" : "Failed to request cancellation"); + return ret; + } +- ++ /* Existing wire field means accepted intent, not confirmed remote exit. */ + cJSON *data = cJSON_CreateObject(); + cJSON_AddBoolToObject(data, "cancelled", true); + ts_api_result_ok(result, data); +diff --git a/components/ts_webui/include/ts_ws_operation.h b/components/ts_webui/include/ts_ws_operation.h +index a971437..af7019e 100644 +--- a/components/ts_webui/include/ts_ws_operation.h ++++ b/components/ts_webui/include/ts_ws_operation.h +@@ -45,3 +45,17 @@ void ts_ws_op_stats(ts_ws_op_kind_t kind, ts_ws_op_stats_t *stats); + + void ts_ws_op_set_maintenance(ts_ws_operation_t *op,bool (*maintain)(void *)); + bool ts_ws_op_needs_tick(void); ++ ++/* Control ownership is separate from observation state. Page controls never use ++ * wildcard acquire. Owner shutdown and exact-ID business cancellation differ. */ ++ts_ws_operation_t *ts_ws_op_shell_control(ts_ws_peer_t peer); ++ts_ws_operation_t *ts_ws_op_shell_owner(void); ++ts_ws_operation_t *ts_ws_op_shell_connection(ts_ws_peer_t peer); ++typedef enum { OP_STOP_NONE=0, OP_STOP_USER=1, OP_STOP_TIMEOUT=2, OP_STOP_MATCH=4 } ts_ws_stop_reason_t; ++typedef enum { OP_BUSINESS_PREPARING, OP_BUSINESS_SUBMITTED, OP_BUSINESS_ENDED } ts_ws_business_phase_t; ++ts_ws_operation_t *ts_ws_op_cancel_exec(uint32_t id); ++bool ts_ws_op_request_stop(ts_ws_operation_t *op,ts_ws_stop_reason_t reason); ++bool ts_ws_op_cancelled(void *context); ++bool ts_ws_op_claim_submit(ts_ws_operation_t *op); ++ts_ws_stop_reason_t ts_ws_op_business_end(ts_ws_operation_t *op,bool deadline); ++bool ts_ws_op_business_running(ts_ws_operation_t *op); +diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c +index e8c2a9c..5d0ca91 100644 +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -60,6 +60,7 @@ typedef enum { + + typedef struct { + atomic_bool active; ++ ts_ws_peer_t peer; /* HTTPD owner writes the connection registry */ + atomic_int fd; + _Atomic(httpd_handle_t) hd; + _Atomic(ws_client_type_t) type; +@@ -273,7 +274,7 @@ static void ssh_poll_task(void *arg) + } + static void ssh_cleanup(void) + { +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0); ++ ts_ws_operation_t *op=ts_ws_op_shell_owner(); + if(!op)return; + ssh_close(op,"closed","SSH session closed"); + ts_ws_op_release(op); +@@ -318,34 +319,33 @@ failed: + set_client_role(peer,WS_CLIENT_TYPE_TERMINAL,TS_LOG_NONE); + ts_ws_op_executor_done(op); + } +-/* Input borrows the original context. Cleanup takes the same resource mutex; +- * the lifecycle lock is never held across SSH I/O. */ +-static void handle_ssh_input(const char *data) ++/* Page control has one ownership gate. The acquired original context remains ++ * pinned across resource I/O; no handler can retarget the current Shell. */ ++static void handle_ssh_control(httpd_req_t *req,ts_ws_peer_t peer,const char *type,cJSON *msg) + { +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; ++ ts_ws_operation_t *op=ts_ws_op_shell_control(peer); ++ if(!op){ssh_request_error(req,"This connection does not own an active SSH session");return;} + ssh_shell_context_t *ctx=ts_ws_op_data(op); +- if(ctx && data){xSemaphoreTake(ctx->io,portMAX_DELAY);if(ctx->shell && ts_ws_op_is_open(op))ts_ssh_shell_write(ctx->shell,data,strlen(data),NULL);xSemaphoreGive(ctx->io);} +- ts_ws_op_release(op); +-} +-static void handle_ssh_disconnect(void) +-{ +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; +- ssh_shell_context_t *ctx=ts_ws_op_data(op); +- if(ctx)ctx->disconnect_requested=true; +- ts_ws_op_release(op); +-} +-static void handle_ssh_signal(const char *signal) +-{ +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; +- ssh_shell_context_t *ctx=ts_ws_op_data(op); +- if(ctx && signal){xSemaphoreTake(ctx->io,portMAX_DELAY);if(ctx->shell && ts_ws_op_is_open(op))ts_ssh_shell_send_signal(ctx->shell,signal);xSemaphoreGive(ctx->io);} +- ts_ws_op_release(op); +-} +-static void handle_ssh_resize(int width,int height) +-{ +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; +- ssh_shell_context_t *ctx=ts_ws_op_data(op); +- if(ctx && width>0 && height>0){xSemaphoreTake(ctx->io,portMAX_DELAY);if(ctx->shell && ts_ws_op_is_open(op))ts_ssh_shell_resize(ctx->shell,width,height);xSemaphoreGive(ctx->io);} ++ if(!strcmp(type,"ssh_disconnect"))ctx->disconnect_requested=true; ++ else { ++ esp_err_t ret=ESP_ERR_INVALID_STATE; ++ xSemaphoreTake(ctx->io,portMAX_DELAY); ++ if(ctx->shell && ts_ws_op_is_open(op)) { ++ if(!strcmp(type,"ssh_input")) { ++ cJSON *data=cJSON_GetObjectItem(msg,"data"); ++ if(cJSON_IsString(data))ret=ts_ssh_shell_write(ctx->shell,data->valuestring,strlen(data->valuestring),NULL); ++ } else if(!strcmp(type,"ssh_signal")) { ++ cJSON *signal=cJSON_GetObjectItem(msg,"signal"); ++ if(cJSON_IsString(signal))ret=ts_ssh_shell_send_signal(ctx->shell,signal->valuestring); ++ } else { ++ cJSON *w=cJSON_GetObjectItem(msg,"width"),*h=cJSON_GetObjectItem(msg,"height"); ++ if(cJSON_IsNumber(w) && cJSON_IsNumber(h) && w->valueint>0 && h->valueint>0) ++ ret=ts_ssh_shell_resize(ctx->shell,w->valueint,h->valueint); ++ } ++ } ++ xSemaphoreGive(ctx->io); ++ if(ret!=ESP_OK)ssh_request_error(req,"SSH control could not be completed for this session"); ++ } + ts_ws_op_release(op); + } + +@@ -376,7 +376,7 @@ static void terminal_output_cb(const char *data, size_t len, void *user_data) + } + + /* 前向声明 */ +-static void cleanup_disconnected_client(int fd); ++static void cleanup_disconnected_client(ts_ws_peer_t peer); + + static esp_err_t add_client(httpd_req_t *req, ws_client_type_t type) + { +@@ -384,6 +384,7 @@ static esp_err_t add_client(httpd_req_t *req, ws_client_type_t type) + esp_err_t ret = ts_ws_peer_open(req, &peer); + if (ret != ESP_OK) return ret; + for (int i = 0; i < MAX_WS_CLIENTS; ++i) if (!s_clients[i].active) { ++ s_clients[i].peer = peer; + s_clients[i].fd = peer.fd; + s_clients[i].hd = peer.server; + s_clients[i].type = type; +@@ -488,10 +489,12 @@ static void start_terminal_session(httpd_req_t *req) + // 检查旧的终端 fd 是否还在活跃客户端列表中 + bool old_fd_active = false; + httpd_handle_t old_hd = NULL; ++ ts_ws_peer_t old_peer={0}; + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == s_terminal_client_fd) { + old_fd_active = true; + old_hd = s_clients[i].hd; ++ old_peer=s_clients[i].peer; + break; + } + } +@@ -526,7 +529,7 @@ static void start_terminal_session(httpd_req_t *req) + } + + // 清理旧会话 +- cleanup_disconnected_client(s_terminal_client_fd); ++ cleanup_disconnected_client(old_peer); + s_terminal_client_fd = -1; + + // 短暂延迟确保关闭消息发送 +@@ -568,19 +571,18 @@ static void start_terminal_session(httpd_req_t *req) + } + + /* 清理断开的客户端 */ +-static void cleanup_disconnected_client(int fd) ++static void cleanup_disconnected_client(ts_ws_peer_t peer) + { + bool was_log_client = false; +- +- // 清理订阅(新增) +- ts_ws_peer_t peer; +- if (ts_ws_peer_get(s_server, fd, &peer)) { ++ int fd=peer.fd; ++ ts_ws_peer_t live; ++ if(ts_ws_peer_get(peer.server,peer.fd,&live) && ts_ws_peer_equal(live,peer)) { + ts_ws_peer_close(peer); + return; + } +- ++ + for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == fd) { ++ if (s_clients[i].active && ts_ws_peer_equal(s_clients[i].peer,peer)) { + // 如果是终端客户端,清理输出回调 + if (s_clients[i].type == WS_CLIENT_TYPE_TERMINAL && s_terminal_client_fd == fd) { + ts_console_clear_output_cb(); +@@ -608,9 +610,9 @@ static void cleanup_disconnected_client(int fd) + static void peer_closed(ts_ws_peer_t peer) + { + ts_ws_client_disconnected(peer); +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0); +- if(op){if(ts_ws_peer_equal(ts_ws_op_peer(op),peer))ssh_close(op,"closed","SSH session closed");ts_ws_op_release(op);} +- cleanup_disconnected_client(peer.fd); ++ ts_ws_operation_t *op=ts_ws_op_shell_connection(peer); ++ if(op){ssh_close(op,"closed","SSH session closed");ts_ws_op_release(op);} ++ cleanup_disconnected_client(peer); + } + + static esp_err_t ws_handler(httpd_req_t *req) +@@ -634,14 +636,14 @@ static esp_err_t ws_handler(httpd_req_t *req) + esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0); + if (ret != ESP_OK) { + TS_LOGD(TAG, "ws_recv_frame error: %s", esp_err_to_name(ret)); +- cleanup_disconnected_client(httpd_req_to_sockfd(req)); ++ cleanup_disconnected_client(peer); + return ret; + } + + // 处理关闭帧 + if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) { + TS_LOGD(TAG, "WebSocket close frame received"); +- cleanup_disconnected_client(httpd_req_to_sockfd(req)); ++ cleanup_disconnected_client(peer); + return ESP_OK; + } + +@@ -661,7 +663,7 @@ static esp_err_t ws_handler(httpd_req_t *req) + + ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len); + if (ret != ESP_OK) { +- cleanup_disconnected_client(httpd_req_to_sockfd(req)); ++ cleanup_disconnected_client(peer); + free(buf); + return ret; + } +@@ -791,31 +793,9 @@ static esp_err_t ws_handler(httpd_req_t *req) + // SSH 连接请求 + handle_ssh_connect(req, msg); + } +- else if (strcmp(type->valuestring, "ssh_input") == 0) { +- // SSH 输入 +- cJSON *data = cJSON_GetObjectItem(msg, "data"); +- if (data && cJSON_IsString(data)) { +- handle_ssh_input(data->valuestring); +- } +- } +- else if (strcmp(type->valuestring, "ssh_disconnect") == 0) { +- // SSH 断开 +- handle_ssh_disconnect(); +- } +- else if (strcmp(type->valuestring, "ssh_signal") == 0) { +- // SSH 信号 (如 INT, TERM) +- cJSON *sig = cJSON_GetObjectItem(msg, "signal"); +- if (sig && cJSON_IsString(sig)) { +- handle_ssh_signal(sig->valuestring); +- } +- } +- else if (strcmp(type->valuestring, "ssh_resize") == 0) { +- // SSH 窗口大小调整 +- cJSON *width = cJSON_GetObjectItem(msg, "width"); +- cJSON *height = cJSON_GetObjectItem(msg, "height"); +- if (width && height && cJSON_IsNumber(width) && cJSON_IsNumber(height)) { +- handle_ssh_resize(width->valueint, height->valueint); +- } ++ else if (!strcmp(type->valuestring,"ssh_input") || !strcmp(type->valuestring,"ssh_disconnect") || ++ !strcmp(type->valuestring,"ssh_signal") || !strcmp(type->valuestring,"ssh_resize")) { ++ handle_ssh_control(req,peer,type->valuestring,msg); + } + /* 日志流订阅 */ + else if (strcmp(type->valuestring, "log_subscribe") == 0) { +@@ -1227,7 +1207,7 @@ typedef struct { + ts_ssh_session_t session; + SemaphoreHandle_t io; + TimerHandle_t timer; +- atomic_bool cancel_requested, timer_closing; ++ atomic_bool timer_closing; + atomic_uint timer_phase; /* 0 none, 1 live, 2 delete, 3 barrier, 4 queued, 5 drained */ + atomic_uint timer_retries; + int64_t timer_retry_at; /* maintenance worker owns pacing */ +@@ -1539,8 +1519,7 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + if (should_stop) { + TS_LOGI(TAG, "Aborting SSH execution (pattern=%d, first_extract=%d)", + pattern_matched, is_first_extract); +- params->cancel_requested = true; +- exec_abort(params); ++ if(ts_ws_op_request_stop(params->op,OP_STOP_MATCH))exec_abort(params); + } + } + } +@@ -1554,8 +1533,7 @@ static void ssh_exec_timeout_callback(TimerHandle_t timer) + ssh_exec_task_params_t *params=pvTimerGetTimerID(timer); + xSemaphoreTake(params->io,portMAX_DELAY); + if(!params->timer_closing) { +- params->cancel_requested=true; +- if(params->session)ts_ssh_abort(params->session); ++ if(ts_ws_op_request_stop(params->op,OP_STOP_TIMEOUT) && params->session)ts_ssh_abort(params->session); + } + xSemaphoreGive(params->io); + } +@@ -1619,8 +1597,8 @@ static void ssh_exec_task(void *arg) + char *key_buf = NULL; + size_t key_len = 0; + +- /* 重置取消请求标志 */ +- /* Initialized by the creator before exposing the original context. */ ++ ts_ws_stop_reason_t stop_reason=OP_STOP_NONE; ++ if(ts_ws_op_cancelled(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + + TS_LOGI(TAG, "SSH exec task started: session_id=%lu, cmd=%s", + (unsigned long)session_id, params->command); +@@ -1635,6 +1613,8 @@ static void ssh_exec_task(void *arg) + params->config.auth.key.private_key_path = NULL; + params->config.auth.key.passphrase = NULL; + } else { ++ stop_reason=ts_ws_op_business_end(params->op,false); ++ if(stop_reason){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + TS_LOGE(TAG, "Failed to load key '%s': %s", params->keyid, esp_err_to_name(ret)); + /* 发送错误消息 */ + if(ts_ws_op_close_begin(params->op)) { +@@ -1651,11 +1631,15 @@ static void ssh_exec_task(void *arg) + } + } + ++ if(ts_ws_op_cancelled(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} ++ + /* 创建 SSH 会话 */ + ts_ssh_session_t created=NULL; + ret = ts_ssh_session_create(¶ms->config, &created); + xSemaphoreTake(params->io,portMAX_DELAY);params->session=created;xSemaphoreGive(params->io); + if (ret != ESP_OK) { ++ stop_reason=ts_ws_op_business_end(params->op,false); ++ if(stop_reason){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + TS_LOGE(TAG, "Failed to create SSH session: %s", esp_err_to_name(ret)); + if(ts_ws_op_close_begin(params->op)) { + cJSON *msg = cJSON_CreateObject(); +@@ -1673,6 +1657,8 @@ static void ssh_exec_task(void *arg) + /* 连接 */ + ret = ts_ssh_connect(params->session); + if (ret != ESP_OK) { ++ stop_reason=ts_ws_op_business_end(params->op,ret==ESP_ERR_TIMEOUT); ++ if(stop_reason)goto execution_finished; + const char *err = ts_ssh_get_error(params->session); + TS_LOGE(TAG, "SSH connect failed: %s", err ? err : "unknown"); + if(ts_ws_op_close_begin(params->op)) { +@@ -1688,6 +1674,8 @@ static void ssh_exec_task(void *arg) + goto cleanup; + } + ++ if(ts_ws_op_cancelled(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} ++ + /* 发送开始消息 */ + { + ts_ws_output_ticket_t start_ticket; +@@ -1737,12 +1725,18 @@ static void ssh_exec_task(void *arg) + } else ts_ws_op_release(params->op); + } + +- /* 流式执行命令 */ ++ /* This lock-ordered claim is the conservative irreversible boundary. ++ * After it, cancellation is cooperative: remote execution may have begun. */ ++ if(!ts_ws_op_claim_submit(params->op)){ret=ESP_ERR_TIMEOUT;goto execution_finished;} + ret = ts_ssh_exec_stream(params->session, params->command, + ssh_exec_output_callback, + params, + &exit_code); + ++execution_finished: ++ TS_WS_TEST_POINT("C04"); ++ stop_reason=ts_ws_op_business_end(params->op,ret==ESP_ERR_TIMEOUT); ++ TS_WS_TEST_POINT("C05"); + xSemaphoreTake(params->io,portMAX_DELAY);params->timer_closing=true;xSemaphoreGive(params->io); + if(params->timer_phase==1){params->timer_phase=2;ts_ws_subscriptions_wake();} + +@@ -1750,7 +1744,7 @@ static void ssh_exec_task(void *arg) + ts_webui_ssh_status_t status = TS_WEBUI_SSH_STATUS_SUCCESS; + + /* 检查是否因超时被取消 */ +- bool was_timeout = params->cancel_requested && (ret == ESP_ERR_TIMEOUT); ++ bool was_timeout = stop_reason==OP_STOP_TIMEOUT; + + /* 优先使用实时匹配结果 */ + bool expect_matched = params->expect_matched; +@@ -1758,7 +1752,11 @@ static void ssh_exec_task(void *arg) + char *extracted_value = params->extracted_value; + params->extracted_value = NULL; /* 转移所有权,避免重复释放 */ + +- if (was_timeout && !params->match_found) { ++ if(stop_reason==OP_STOP_USER) { ++ status=TS_WEBUI_SSH_STATUS_CANCELLED; ++ } else if(stop_reason==OP_STOP_MATCH) { ++ status=params->fail_matched?TS_WEBUI_SSH_STATUS_MATCH_FAILED:TS_WEBUI_SSH_STATUS_MATCH_SUCCESS; ++ } else if (was_timeout && !params->match_found) { + /* 超时且未匹配成功 */ + status = TS_WEBUI_SSH_STATUS_TIMEOUT; + TS_LOGW(TAG, "SSH exec timed out without match"); +@@ -1956,6 +1954,7 @@ static void ssh_exec_task(void *arg) + } + + cleanup: ++ ts_ws_op_business_end(params->op,false); + /* 清理密钥缓冲区 */ + if (key_buf) { + memset(key_buf, 0, key_len); +@@ -2000,6 +1999,8 @@ static esp_err_t ts_webui_ssh_exec_start_ex_impl(ts_ws_operation_t *op, const ch + + /* 配置 SSH */ + params->config = (ts_ssh_config_t)TS_SSH_DEFAULT_CONFIG(); ++ params->config.cancelled=ts_ws_op_cancelled; ++ params->config.cancel_context=op; + params->config.host = strdup(host); + params->config.port = port; + params->config.username = strdup(user); +@@ -2199,19 +2200,17 @@ void ts_webui_ssh_result_free(ts_webui_ssh_result_t *result) + + esp_err_t ts_webui_ssh_exec_cancel(uint32_t session_id) + { +- if(!session_id)return ESP_ERR_INVALID_STATE; +- ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,session_id); ++ ts_ws_operation_t *op=ts_ws_op_cancel_exec(session_id); + if(!op)return ESP_ERR_INVALID_STATE; + ssh_exec_task_params_t *params=ts_ws_op_data(op); +- bool running=ts_ws_op_executing(op); +- if(params && running)exec_abort(params); ++ exec_abort(params); /* intent is already persistent, even without a session */ + ts_ws_op_release(op); +- return running?ESP_OK:ESP_ERR_INVALID_STATE; ++ return ESP_OK; /* accepted request, not remote termination confirmation */ + } + + bool ts_webui_ssh_exec_is_running(uint32_t session_id) + { + ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,session_id); + if(!op)return false; +- bool running=ts_ws_op_executing(op);ts_ws_op_release(op);return running; ++ bool running=ts_ws_op_business_running(op);ts_ws_op_release(op);return running; + } +diff --git a/components/ts_webui/src/ts_ws_operation.c b/components/ts_webui/src/ts_ws_operation.c +index 1f8ee93..6b5968c 100644 +--- a/components/ts_webui/src/ts_ws_operation.c ++++ b/components/ts_webui/src/ts_ws_operation.c +@@ -11,6 +11,10 @@ struct ts_ws_operation { + ts_ws_op_stats_t ledger; + ts_ws_op_kind_t kind; + bool initializing, builder; ++ bool business_accepted; ++ ts_ws_business_phase_t business; ++ ts_ws_stop_reason_t first_stop; ++ unsigned stop_reasons; + ts_ws_peer_t peer, terminal_peers[TS_WS_CONNECTIONS]; + unsigned terminal_count; + ts_ws_reservation_t terminal; +@@ -75,7 +79,7 @@ void ts_ws_op_executor_done(ts_ws_operation_t *op) { + } + bool ts_ws_op_executing(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.executors!=0;OP_UNLOCK();return yes; } + bool ts_ws_op_open(ts_ws_operation_t *op) { +- OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;if(yes)op->ledger.phase=OP_OPEN;OP_UNLOCK();return yes; ++ OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;if(yes){op->ledger.phase=OP_OPEN;op->business_accepted=true;}OP_UNLOCK();return yes; + } + bool ts_ws_op_is_open(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.phase==OP_OPEN;OP_UNLOCK();return yes; } + bool ts_ws_op_starting(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;OP_UNLOCK();return yes; } +@@ -215,3 +219,58 @@ void ts_ws_op_poll(void) { + OP_LOCK();s_op_tick=tick;OP_UNLOCK(); + } + void ts_ws_op_stats(ts_ws_op_kind_t kind,ts_ws_op_stats_t *stats) {OP_LOCK();*stats=s_ops[kind].ledger;OP_UNLOCK();} ++ ++/* All identity checks, reference acquisition and control decisions linearize ++ * under the same operation lock. No resource or network work under this lock. */ ++static ts_ws_operation_t *shell_for_peer(ts_ws_peer_t peer,bool control) { ++ OP_LOCK();ts_ws_operation_t *op=&s_ops[TS_WS_OP_SHELL]; ++ if(op->initializing || op->ledger.phase==OP_FREE || op->ledger.phase==OP_RECLAIMING || ++ (control && op->ledger.phase!=OP_OPEN) || !ts_ws_peer_equal(op->peer,peer))op=NULL; ++ else op->ledger.refs++; ++ OP_UNLOCK();return op; ++} ++ts_ws_operation_t *ts_ws_op_shell_control(ts_ws_peer_t peer) { ++ ts_ws_operation_t *op=shell_for_peer(peer,true);TS_WS_TEST_POINT("C01");return op; ++} ++ts_ws_operation_t *ts_ws_op_shell_connection(ts_ws_peer_t peer) { ++ return shell_for_peer(peer,false); ++} ++ts_ws_operation_t *ts_ws_op_shell_owner(void) { ++ return ts_ws_op_acquire(TS_WS_OP_SHELL,0); /* service/connection owner only */ ++} ++static bool request_stop_locked(ts_ws_operation_t *op,ts_ws_stop_reason_t reason) { ++ if(op->kind!=TS_WS_OP_EXEC || !op->business_accepted || op->business==OP_BUSINESS_ENDED)return false; ++ op->stop_reasons|=reason; ++ if(!op->first_stop)op->first_stop=reason; ++ return true; ++} ++ts_ws_operation_t *ts_ws_op_cancel_exec(uint32_t id) { ++ OP_LOCK();ts_ws_operation_t *op=&s_ops[TS_WS_OP_EXEC]; ++ if(!id || op->ledger.phase==OP_FREE || op->ledger.phase==OP_RECLAIMING || ++ op->ledger.identity!=id || !request_stop_locked(op,OP_STOP_USER))op=NULL; ++ else op->ledger.refs++; ++ OP_UNLOCK();return op; ++} ++bool ts_ws_op_request_stop(ts_ws_operation_t *op,ts_ws_stop_reason_t reason) { ++ OP_LOCK();bool accepted=request_stop_locked(op,reason);OP_UNLOCK();return accepted; ++} ++bool ts_ws_op_cancelled(void *context) { ++ ts_ws_operation_t *op=context;OP_LOCK();bool yes=op->stop_reasons!=0;OP_UNLOCK();return yes; ++} ++bool ts_ws_op_claim_submit(ts_ws_operation_t *op) { ++ TS_WS_TEST_POINT("C02");OP_LOCK(); ++ bool yes=op->business_accepted && op->business==OP_BUSINESS_PREPARING && !op->stop_reasons; ++ if(yes)op->business=OP_BUSINESS_SUBMITTED; ++ OP_UNLOCK();TS_WS_TEST_POINT("C03");return yes; ++} ++ts_ws_stop_reason_t ts_ws_op_business_end(ts_ws_operation_t *op,bool deadline) { ++ OP_LOCK(); ++ if(op->business!=OP_BUSINESS_ENDED){ ++ if(deadline && !op->first_stop)request_stop_locked(op,OP_STOP_TIMEOUT); ++ op->business=OP_BUSINESS_ENDED; ++ } ++ ts_ws_stop_reason_t reason=op->first_stop;OP_UNLOCK();return reason; ++} ++bool ts_ws_op_business_running(ts_ws_operation_t *op) { ++ OP_LOCK();bool yes=op->business_accepted && op->business!=OP_BUSINESS_ENDED;OP_UNLOCK();return yes; ++} +diff --git a/components/ts_webui/web/js/lang/en-US.js b/components/ts_webui/web/js/lang/en-US.js +index 9240a21..8eaf87b 100644 +--- a/components/ts_webui/web/js/lang/en-US.js ++++ b/components/ts_webui/web/js/lang/en-US.js +@@ -110,7 +110,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { + "sshCheckOutput": "Use the buttons above to check logs or process status.\n", + "sshBegin": "--- Execution started ---\n", + "sshEnd": "\n--- Execution ended ---\n", +- "sshCancelOutput": "\nExecution cancelled.\n", ++ "sshCancelOutput": "\nCancellation handling finished; remote command termination is not confirmed.\n", + "noOutput": "(No output)\n", + "serviceStoppedOutput": "The service has stopped.\n", + "processStoppedOutput": "The process has stopped.\n", +@@ -194,7 +194,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { + "sshDiagnostics": "Reported status: {status}; exit code: {code}", + "sshUnknown": "The command result is unconfirmed. Check the output and status details.", + "sshTimeout": "The command timed out. Check the output to see what was executed.", +- "sshCancelled": "Command execution was cancelled.", ++ "sshCancelled": "Cancellation handling finished; remote command termination is not confirmed.", + "sshFailureOutput": "The output matched a configured failure condition. Check the command output.", + "sshExpectedMissing": "The command ended without the expected output.", + "sshExpectedFound": "The expected output was detected. Waiting for the final result.", +@@ -1714,7 +1714,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { + commandCompletedCode: "The command did not complete successfully (exit code: {code}). Check its output.", + execError: 'Execution error', + execErrorMsg: 'Execution error: {msg}', +- commandCancelled: 'Command cancelled', ++ commandCancelled: 'Cancellation handled; remote outcome unconfirmed', + hostFingerprintDeleted: 'Host fingerprint deleted', + hostInfoEmpty: "No connection settings are available for this host. Check its settings.", + testingConnection: 'Testing connection to {host}...', +diff --git a/components/ts_webui/web/js/lang/zh-CN.js b/components/ts_webui/web/js/lang/zh-CN.js +index 2249198..cfebef2 100644 +--- a/components/ts_webui/web/js/lang/zh-CN.js ++++ b/components/ts_webui/web/js/lang/zh-CN.js +@@ -110,7 +110,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { + "sshCheckOutput": "请使用上方按钮查看日志或进程状态。\n", + "sshBegin": "--- 开始执行 ---\n", + "sshEnd": "\n--- 执行结束 ---\n", +- "sshCancelOutput": "\n执行已取消。\n", ++ "sshCancelOutput": "\n取消处理已结束;远端命令是否终止尚未确认。\n", + "noOutput": "(无输出)\n", + "serviceStoppedOutput": "服务已停止。\n", + "processStoppedOutput": "进程已停止。\n", +@@ -194,7 +194,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { + "sshDiagnostics": "返回状态:{status};退出码:{code}", + "sshUnknown": "无法确认命令结果,请查看输出和状态详情。", + "sshTimeout": "命令执行超时,请查看输出确认实际执行情况。", +- "sshCancelled": "命令执行已取消。", ++ "sshCancelled": "取消处理已结束;远端命令是否终止尚未确认。", + "sshFailureOutput": "命令输出命中了配置的失败条件,请查看输出。", + "sshExpectedMissing": "命令已结束,但未检测到配置的预期输出。", + "sshExpectedFound": "已检测到预期输出,等待最终执行结果。", +@@ -1674,7 +1674,7 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { + commandCompletedCode: "命令未成功完成,退出码:{code}。请查看命令输出。", + execError: '执行出错', + execErrorMsg: '执行出错: {msg}', +- commandCancelled: '命令已取消', ++ commandCancelled: '取消处理已结束,远端结果未确认', + hostFingerprintDeleted: '已删除主机指纹', + hostInfoEmpty: "没有找到此主机的连接配置,请检查主机设置。", + testingConnection: '正在测试连接 {host}...', +diff --git a/tests/prompts/regression.test.cjs b/tests/prompts/regression.test.cjs +index d943fee..d6bf002 100644 +--- a/tests/prompts/regression.test.cjs ++++ b/tests/prompts/regression.test.cjs +@@ -81,6 +81,12 @@ for(const lang of ['zh-CN','en-US']) { + h.run('currentExecSessionId=17;toastDeadline=0;');h.ctx.handleSshExecMessage({type:'ssh_exec_done',session_id:17,status,exit_code,fail_matched}); + assert.equal(h.el('toast').textContent,h.ctx.t('promptRepair.'+key));assert.equal(h.el('match-final-status').textContent,h.ctx.t('promptRepair.'+key)); + } ++ h.run('currentExecSessionId=17;toastDeadline=0;'); ++ h.ctx.handleSshExecMessage({type:'ssh_exec_cancelled',session_id:17}); ++ assert.equal(h.run('currentExecSessionId'),null); ++ assert(h.el('exec-result').textContent.includes(h.ctx.t('promptRepair.sshCancelOutput'))); ++ assert.match(h.el('exec-result').textContent,lang==='zh-CN'?/远端命令是否终止尚未确认/:/remote command termination is not confirmed/); ++ assert.equal(h.el('toast').textContent,h.ctx.t('toast.commandCancelled')); + assert.equal(h.ctx.sshTerminalResult({status:'match_failed',success:true}).key,'sshUnknown'); + h.run('currentExecSessionId=17;toastDeadline=0;');h.ctx.handleSshExecMessage({type:'ssh_exec_match',session_id:17,is_final:true,fail_matched:true}); + assert.equal(h.el('toast').textContent,h.ctx.t('promptRepair.sshFailureOutput')); +diff --git a/tests/ws_subscriptions/test_operation_adapter.c b/tests/ws_subscriptions/test_operation_adapter.c +index 89d428b..fa881f7 100644 +--- a/tests/ws_subscriptions/test_operation_adapter.c ++++ b/tests/ws_subscriptions/test_operation_adapter.c +@@ -68,7 +68,10 @@ static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,voi + #undef heap_caps_calloc + #undef xTaskCreate + #undef xTaskCreateWithCaps +-struct ts_ssh_session_s {bool aborted;}; ++struct ts_ssh_session_s {bool aborted;ts_ssh_config_t config;}; ++static unsigned control_writes,control_signals,control_resizes,commands_submitted; ++static void (*stage_hook)(const char *); ++static void stage(const char *name){if(stage_hook)stage_hook(name);} + struct ts_ssh_shell_s {bool active;}; + static unsigned aborts,variable_writes,session_destroys; + static int remote_failure; +@@ -89,8 +92,8 @@ BaseType_t xTimerPendFunctionCall(void(*fn)(void*,uint32_t),void *arg,uint32_t v + assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){fn,arg,v,NULL};return pdPASS; + } + static void timer_pump(void){while(timer_queued){typeof(timer_queue[0]) q=timer_queue[0];memmove(timer_queue,timer_queue+1,--timer_queued*sizeof(*timer_queue));if(q.deleted){free(q.deleted);host_timer=NULL;}else q.fn(q.arg,q.value);}} +-esp_err_t ts_ssh_session_create(const ts_ssh_config_t*c,ts_ssh_session_t *out){(void)c;if(remote_failure==1)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));return *out?ESP_OK:ESP_ERR_NO_MEM;} +-esp_err_t ts_ssh_connect(ts_ssh_session_t s){(void)s;return remote_failure==2?ESP_FAIL:ESP_OK;} ++esp_err_t ts_ssh_session_create(const ts_ssh_config_t*c,ts_ssh_session_t *out){stage("create");if(remote_failure==1)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));if(*out)(*out)->config=*c;return *out?ESP_OK:ESP_ERR_NO_MEM;} ++esp_err_t ts_ssh_connect(ts_ssh_session_t s){stage("connect");if(s->config.cancelled && s->config.cancelled(s->config.cancel_context))return ESP_ERR_TIMEOUT;stage("auth");return remote_failure==2?ESP_FAIL:ESP_OK;} + const char *ts_ssh_get_error(ts_ssh_session_t s){(void)s;return "fake network error";} + esp_err_t ts_ssh_disconnect(ts_ssh_session_t s){(void)s;return ESP_OK;} + esp_err_t ts_ssh_session_destroy(ts_ssh_session_t s){session_destroys++;tracked_free(s);return ESP_OK;} +@@ -99,14 +102,14 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t s,const ts_shell_config_t*c,ts_ssh_ + bool ts_ssh_shell_is_active(ts_ssh_shell_t s){return s&&s->active;} + esp_err_t ts_ssh_shell_close(ts_ssh_shell_t s){tracked_free(s);return 0;} + esp_err_t ts_ssh_shell_read(ts_ssh_shell_t s,char *b,size_t n,size_t *out){(void)b;(void)n;*out=0;s->active=false;return 0;} +-esp_err_t ts_ssh_shell_write(ts_ssh_shell_t s,const char *b,size_t n,size_t *out){(void)s;(void)b;(void)n;(void)out;return 0;} +-esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t s,uint16_t w,uint16_t h){(void)s;(void)w;(void)h;return 0;} +-esp_err_t ts_ssh_shell_send_signal(ts_ssh_shell_t s,const char *signal){(void)s;(void)signal;return 0;} ++esp_err_t ts_ssh_shell_write(ts_ssh_shell_t s,const char *b,size_t n,size_t *out){(void)s;(void)b;(void)n;(void)out;control_writes++;return 0;} ++esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t s,uint16_t w,uint16_t h){(void)s;(void)w;(void)h;control_resizes++;return 0;} ++esp_err_t ts_ssh_shell_send_signal(ts_ssh_shell_t s,const char *signal){(void)s;(void)signal;control_signals++;return 0;} + esp_err_t ts_ssh_exec_stream(ts_ssh_session_t s,const char *command,ts_ssh_output_cb_t cb,void *arg,int *code){ +- (void)command;if(remote_hook)remote_hook();if(remote_timeout && host_timer)host_timer->fn(host_timer); +- cb("value=42\n",9,false,arg);*code=0;return s->aborted?ESP_ERR_TIMEOUT:ESP_OK; ++ (void)command;stage("submit");if(s->config.cancelled && s->config.cancelled(s->config.cancel_context))return ESP_ERR_TIMEOUT;commands_submitted++;if(remote_hook)remote_hook();if(remote_timeout && host_timer)host_timer->fn(host_timer); ++ cb("value=42\n",9,false,arg);*code=0;return s->aborted || (s->config.cancelled && s->config.cancelled(s->config.cancel_context))?ESP_ERR_TIMEOUT:ESP_OK; + } +-esp_err_t ts_keystore_load_private_key(const char *id,char **out,size_t *n){(void)id;(void)out;(void)n;return ESP_FAIL;} ++esp_err_t ts_keystore_load_private_key(const char *id,char **out,size_t *n){(void)id;stage("key");*out=host_strdup("fake-key");*n=9;return ESP_OK;} + esp_err_t ts_variable_upsert(const ts_auto_variable_t *v){(void)v;variable_writes++;return 0;} + esp_err_t ts_console_exec(const char *cmd,ts_cmd_result_t *result){(void)cmd;memset(result,0,sizeof(*result));return 0;} + esp_err_t ts_console_clear_output_cb(void){return 0;} +@@ -165,7 +168,7 @@ static void stop_progress_shell(void){ + } + static void operation_cross_tests(void){ + uint32_t id;ts_ws_op_stats_t ledger; +- setup();connect_shell();unsigned dc=disconnecting_frames;handle_ssh_disconnect();shell_task.fn(shell_task.arg);finish_all();assert(disconnecting_frames==dc+1); ++ setup();connect_shell();unsigned dc=disconnecting_frames;incoming="{\"type\":\"ssh_disconnect\"}";reqs[1].method=1;current=(void*)3;assert(ws_handler(&reqs[1])==ESP_OK);current=(void*)1;incoming=NULL;shell_task.fn(shell_task.arg);finish_all();assert(disconnecting_frames==dc+1); + setup();terminal_frames=output_frames=0;output_after_terminal=false;connect_shell(); + ssh_shell_context_t *ctx=shell_task.arg;paused_id=ts_ws_op_id(ctx->op); + ts_ws_message_t *m=ts_ws_message_text("block",5); +diff --git a/tests/ws_subscriptions/test_control.c b/tests/ws_subscriptions/test_control.c +new file mode 100644 +index 0000000..7fcfe31 +--- /dev/null ++++ b/tests/ws_subscriptions/test_control.c +@@ -0,0 +1,142 @@ ++#define OP_ADAPTER_NO_MAIN ++#include "test_operation_adapter.c" ++#define TS_API_ERR_NOT_FOUND 2 ++#define TS_API_ERR_INTERNAL 7 ++static void ts_api_result_error(ts_api_result_t *r,int code,const char *message){(void)message;r->code=code;} ++static void ts_api_result_ok(ts_api_result_t *r,cJSON *data){r->code=0;r->data=data;} ++#include "api_cancel.inc" ++static void dispatch(unsigned fd,const char *text){incoming=text;reqs[fd].method=1;current=(void*)3;assert(ws_handler(&reqs[fd])==ESP_OK);current=(void*)1;incoming=NULL;} ++static void shell_on(unsigned fd){cJSON *j=cJSON_Parse("{\"host\":\"fake\",\"user\":\"fake\"}");current=(void*)3;handle_ssh_connect(&reqs[fd],j);current=(void*)1;cJSON_Delete(j);} ++static bool ownership_case(void){ ++ setup();connect_shell();ssh_cleanup();shell_task.fn(shell_task.arg);drive_all();shell_on(2); ++ unsigned w=control_writes,s=control_signals,r=control_resizes; ++ dispatch(1,"{\"type\":\"ssh_input\",\"data\":\"bad\"}");dispatch(1,"{\"type\":\"ssh_signal\",\"signal\":\"INT\"}");dispatch(1,"{\"type\":\"ssh_resize\",\"width\":90,\"height\":30}");dispatch(1,"{\"type\":\"ssh_disconnect\"}"); ++ bool ok=control_writes==w && control_signals==s && control_resizes==r && !((ssh_shell_context_t*)shell_task.arg)->disconnect_requested; ++ ssh_cleanup();shell_task.fn(shell_task.arg);finish_all();return ok; ++} ++static bool early_cancel_case(void){ ++ setup();uint32_t id;assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ unsigned before=commands_submitted;assert(ts_webui_ssh_exec_cancel(id)==ESP_OK);exec_task.fn(exec_task.arg);finish_all();return commands_submitted==before; ++} ++static uint32_t target_id; ++static const char *cancel_stage; ++static unsigned cancelled_frames,timeout_frames,match_frames; ++static void result_observe(httpd_ws_frame_t *frame){ ++ observe(frame);const char *s=(char*)frame->payload; ++ if(strstr(s,"ssh_exec_cancelled"))cancelled_frames++; ++ if(strstr(s,"\"status\":\"timeout\""))timeout_frames++; ++ if(strstr(s,"\"status\":\"match_success\""))match_frames++; ++} ++static void cancel_now(void){ ++ assert(ts_webui_ssh_exec_cancel(target_id)==ESP_OK); ++ assert(ts_webui_ssh_exec_cancel(target_id)==ESP_OK); ++ assert(ts_webui_ssh_exec_cancel(target_id+1)==ESP_ERR_INVALID_STATE); ++} ++static void cancel_at(const char *name){if(cancel_stage && !strcmp(name,cancel_stage)){cancel_stage=NULL;cancel_now();}} ++static void ended_rejects(void){ ++ assert(!ts_webui_ssh_exec_is_running(target_id)); ++ assert(ts_webui_ssh_exec_cancel(target_id)==ESP_ERR_INVALID_STATE); ++} ++static void close_borrowed(void){ ++ ssh_shell_context_t *ctx=shell_task.arg;uint32_t id=ts_ws_op_id(ctx->op); ++ ssh_cleanup();shell_task.fn(shell_task.arg);drive_all();shell_on(2); ++ ts_ws_op_stats_t state;ts_ws_op_stats(TS_WS_OP_SHELL,&state); ++ assert(state.identity==id && state.refs && state.phase!=OP_FREE); ++} ++static void controls(void){ ++ setup();connect_shell();unsigned w=control_writes,s=control_signals,r=control_resizes; ++ dispatch(1,"{\"type\":\"ssh_input\",\"data\":\"ok\"}"); ++ dispatch(1,"{\"type\":\"ssh_signal\",\"signal\":\"INT\"}"); ++ dispatch(1,"{\"type\":\"ssh_resize\",\"width\":90,\"height\":30}"); ++ assert(control_writes==w+1 && control_signals==s+1 && control_resizes==r+1); ++ dispatch(1,"{\"type\":\"ssh_disconnect\"}");assert(((ssh_shell_context_t*)shell_task.arg)->disconnect_requested); ++ shell_task.fn(shell_task.arg);finish_all(); ++ // A borrow survives close/cleanup and prevents reuse until its last access. ++ setup();connect_shell();w=control_writes;barrier_name="C01";barrier_action=close_borrowed; ++ dispatch(1,"{\"type\":\"ssh_input\",\"data\":\"late\"}");assert(!barrier_action && control_writes==w); ++ drive_all();shell_on(2);assert(ts_ws_op_is_open(((ssh_shell_context_t*)shell_task.arg)->op));ssh_cleanup();shell_task.fn(shell_task.arg);finish_all(); ++ // Reused fd, same HTTPD handle: old peer and old close cannot touch replacement. ++ setup();connect_shell();ts_ws_peer_t old=*(ts_ws_peer_t*)reqs[1].sess_ctx; ++ close_peer(1);shell_task.fn(shell_task.arg);drive_all(); ++ reqs[1]=(httpd_req_t){.handle=(void*)11,.fd=1};current=(void*)3;assert(add_client(&reqs[1],WS_CLIENT_TYPE_EVENT)==0);current=(void*)1;connect_shell(); ++ ts_ws_peer_t replacement=*(ts_ws_peer_t*)reqs[1].sess_ctx,found; ++ current=(void*)3;peer_closed(old);current=(void*)1; ++ assert(ts_ws_peer_get(replacement.server,replacement.fd,&found) && ts_ws_peer_equal(found,replacement)); ++ assert(ts_ws_op_is_open(((ssh_shell_context_t*)shell_task.arg)->op)); ++ httpd_req_t stale=reqs[1];stale.method=1;stale.sess_ctx=&old;incoming="{\"type\":\"ssh_disconnect\"}"; ++ current=(void*)3;assert(ws_handler(&stale)==ESP_ERR_INVALID_STATE);current=(void*)1;incoming=NULL; ++ old=replacement;old.epoch++;assert(!ts_ws_op_shell_control(old));old=replacement;old.server=(void*)12;assert(!ts_ws_op_shell_control(old)); ++ delay_hook=stop_progress_shell;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL;finish_ws(); ++ puts("PASS actual WS controls: all four foreign controls rejected, owner controls work; borrowed original pinned, fd/epoch/server reuse and late close isolated; owner stop drains"); ++} ++static void cancellation_phases(void){ ++ const char *phases[]={"key","create","connect","auth","submit","C02","C03","C04"}; ++ for(unsigned i=0;iop)); ++ cancel_now(); ++} ++static void reason_tests(void){ ++ immediate=true; ++ ts_webui_ssh_options_t opts={.timeout_ms=1000,.collect_output=true,.extract_pattern="value=(.*)",.stop_on_match=true}; ++ setup();unsigned c=cancelled_frames,t=timeout_frames,m=match_frames; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&target_id)==0); ++ remote_hook=cancel_now;exec_task.fn(exec_task.arg);remote_hook=NULL;finish_all();assert(cancelled_frames==c+2 && match_frames==m && timeout_frames==t); ++ setup();assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&target_id)==0); ++ exec_task.fn(exec_task.arg);finish_all();assert(match_frames==m+2); ++ setup();opts.stop_on_match=false;opts.extract_pattern=NULL;t=timeout_frames;c=cancelled_frames; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&target_id)==0); ++ remote_timeout=true;exec_task.fn(exec_task.arg);remote_timeout=false;finish_all();assert(timeout_frames==t+2 && cancelled_frames==c); ++ immediate=false;setup();assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&target_id)==0); ++ remote_hook=stop_busy_cancel;exec_task.fn(exec_task.arg);remote_hook=NULL; ++ drive_all();finish_ws(); ++ puts("PASS USER/TIMEOUT/MATCH keep distinct results; service stop busy does not cancel business, accepted user intent survives stop retry and all resource ledgers drain"); ++} ++static void observe_then_cancel(void){ ++ fail_observation_business_continues();cancel_now(); ++} ++static void timeout_then_cancel(void){host_timer->fn(host_timer);cancel_now();} ++static void intersecting_failures(void){ ++ setup();unsigned c=cancelled_frames; ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&target_id)==0); ++ remote_hook=observe_then_cancel;exec_task.fn(exec_task.arg);remote_hook=NULL; ++ finish_all();assert(cancelled_frames==c); /* sealed observation failure is not rewritten */ ++ setup();unsigned t=timeout_frames;c=cancelled_frames; ++ ts_webui_ssh_options_t opts={.timeout_ms=1000,.collect_output=true}; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&target_id)==0); ++ remote_hook=timeout_then_cancel;exec_task.fn(exec_task.arg);remote_hook=NULL;finish_all(); ++ assert(timeout_frames==t+2 && cancelled_frames==c); ++ puts("PASS output failure seals observation without cancelling business; later explicit cancel still reaches original executor without rewriting terminal; earlier timeout retains reason"); ++} ++static void api_controls(void){ ++ s_op_sequence=0x80000000u; /* valid public uint32 IDs must not pass through signed valueint */ ++ setup();assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&target_id)==0); ++ const char *bad[]={"{}","{\"session_id\":0}","{\"session_id\":-1}","{\"session_id\":1.5}","{\"session_id\":4294967296}","{\"session_id\":\"1\"}"}; ++ for(unsigned i=0;iop));} ++ cJSON *j=cJSON_CreateObject();cJSON_AddNumberToObject(j,"session_id",target_id); ++ ts_api_result_t r={0};assert(api_ssh_cancel(j,&r)==0 && cJSON_IsTrue(cJSON_GetObjectItem(r.data,"cancelled")));cJSON_Delete(r.data); ++ exec_task.fn(exec_task.arg);drive_all();r=(ts_api_result_t){0};assert(api_ssh_cancel(j,&r)!=0);cJSON_Delete(j);finish_all(); ++ puts("PASS actual ssh.cancel API exact-ID validation and accepted-intent response; ended operations reject without wildcard control"); ++} ++int main(int argc,char **argv){ ++ cJSON_Hooks h={tracked_malloc,tracked_free};cJSON_InitHooks(&h);sent_hook=result_observe; ++ if(argc==2){bool ok=!strcmp(argv[1],"v1")?ownership_case():early_cancel_case();printf("%s business_contract=%s\n",argv[1],ok?"PASS":"FAIL");return ok?0:1;} ++ assert(ownership_case());assert(early_cancel_case());controls();cancellation_phases();reason_tests();intersecting_failures();api_controls();return 0; ++} +diff --git a/tests/ws_subscriptions/run_control.sh b/tests/ws_subscriptions/run_control.sh +new file mode 100644 +index 0000000..cc2bed1 +--- /dev/null ++++ b/tests/ws_subscriptions/run_control.sh +@@ -0,0 +1,18 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++: "${IDF_PATH:?NOT RUN: set IDF_PATH to the project SDK}" ++build=$(mktemp -d /tmp/ts-ws-adapter.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++cjson="$IDF_PATH/components/json/cJSON" ++python3 - "$build" <<'PYCODE' ++from pathlib import Path ++import sys ++s=Path('components/ts_api/src/ts_api_ssh.c').read_text() ++a=s.index('static esp_err_t api_ssh_cancel('); b=s.index('\n}',a)+2 ++Path(sys.argv[1],'api_cancel.inc').write_text(s[a:b]) ++PYCODE ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -Wno-macro-redefined -fsanitize=address,undefined \ ++ -I"$build" -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -Icomponents/ts_security/include -Icomponents/ts_automation/include -Icomponents/ts_drivers/include -Icomponents/ts_console/include -Icomponents/ts_net/include -I"$cjson" \ ++ tests/ws_subscriptions/test_control.c "$cjson/cJSON.c" -o "$build/adapter" ++"$build/adapter" "$@" +diff --git a/tests/ws_subscriptions/replay_control_baseline.py b/tests/ws_subscriptions/replay_control_baseline.py +new file mode 100644 +index 0000000..58c6fcc +--- /dev/null ++++ b/tests/ws_subscriptions/replay_control_baseline.py +@@ -0,0 +1,21 @@ ++from pathlib import Path ++import hashlib,json,os,shutil,subprocess,tarfile,tempfile ++root=Path(__file__).resolve().parents[2]; proof=root/'docs/repair/ws-control' ++for f,h in json.loads((proof/'baseline-evidence.json').read_text()).items(): ++ assert hashlib.sha256((proof/f).read_bytes()).hexdigest()==h,f ++with tempfile.TemporaryDirectory(prefix='ts-control-baseline-') as tmp: ++ base=Path(tmp) ++ with tarfile.open(proof/'baseline.tar.gz') as t:t.extractall(base) ++ for f,h in json.loads((proof/'baseline.json').read_text())['sha256'].items(): ++ assert hashlib.sha256((base/f).read_bytes()).hexdigest()==h,f ++ for path in (root/'components').iterdir(): ++ if not (base/'components'/path.name).exists():(base/'components'/path.name).symlink_to(path,target_is_directory=True) ++ for path in (root/'components/ts_security/include').iterdir(): ++ dest=base/'components/ts_security/include'/path.name ++ if not dest.exists():dest.symlink_to(path) ++ for src,dst in [('baseline-adapter.c','test_operation_adapter.c'),('baseline-control.c','test_control.c')]:shutil.copyfile(proof/src,base/'tests/ws_subscriptions'/dst) ++ shutil.copyfile(root/'tests/ws_subscriptions/run_control.sh',base/'tests/ws_subscriptions/run_control.sh') ++ for case in ['v1','v2']: ++ r=subprocess.run(['bash','tests/ws_subscriptions/run_control.sh',case],cwd=base,capture_output=True,text=True) ++ print(r.stdout,end='');assert r.returncode==1 and case+' business_contract=FAIL' in r.stdout and not r.stderr,r.stderr ++ print('CONFIRMED: both failures are production business assertions; complete frozen source hashes verified') diff --git a/docs/repair/ws-control/control-contract.md b/docs/repair/ws-control/control-contract.md new file mode 100644 index 0000000..801ad5d --- /dev/null +++ b/docs/repair/ws-control/control-contract.md @@ -0,0 +1,28 @@ +# 控制请求契约(实施前与迁移决定) + +基线 1591ecc;本轮仅本地修改、测试、编译。保留其他未跟踪文件。 + +| 请求/来源 | 原入口与缺陷 | 统一目标、接受点及执行者 | 结果与引用释放 | +|---|---|---|---| +| Shell 输入 / WS ssh_input | wildcard current Shell | 从 req 的完整 peer,在 op 锁内匹配原 peer + OPEN 并取引用;资源 mutex 下写原 shell | 不匹配向请求者报既有 error;执行完释放;不改投 | +| Shell 断开 / WS ssh_disconnect | wildcard + ctx atomic | 同一目标获取;原 ctx 保存 disconnect 意图,原 poller 顺序发送 disconnecting 并关闭 | 接受非关闭确认;poller 保活;请求释放借用 | +| Shell 信号 / WS ssh_signal | wildcard current Shell | 同一目标获取;原 shell 资源 mutex 下发送 | 同输入 | +| Shell resize / WS ssh_resize | wildcard current Shell | 同一目标获取;原 shell 资源 mutex 下调整 | 同输入 | +| Exec 取消 / ssh.cancel API | id acquire + session 存在才 abort | exact 非零操作 ID、已接受业务且未 ENDED,在 op 锁内保存 USER 意图并取原引用;底层 config.cancelled 持续读取原 op | 既有 cancelled:true 仅表示请求接受;结束后 INVALID_STATE;调用退出释放 | +| 业务超时 / 原 timer 或驱动 deadline | 与匹配共享 cancel_requested | 原 timer 上下文保活,登记 TIMEOUT;驱动返回时在业务结束决定点记录无其他原因的 deadline | timeout;timer 原有 daemon 排空后释放 | +| 匹配停止 / 原 executor 输出回调 | 与超时共用标记 | 原上下文登记 MATCH;复用协作停止,不改变匹配规则 | match_success/failed;不覆盖较早 USER 原因;同步回调释放 | +| 服务停止 / service owner | current Shell / busy Exec | 独立 owner Shell acquire;HTTPD barrier 后关闭原 Shell;Exec 只等待或 busy,不登记业务取消 | busy/timeout 保留结果通道及依赖;借用释放,执行者自行退出 | + +观察失败只封口网页观察,不登记任何业务停止原因。业务阶段与 OP_OPEN/CLOSING 等观察阶段正交:PREPARING -> SUBMIT_CLAIMED -> ENDED。取消和 claim 在 s_op_lock 内排序;claim 前取消保证不再调用命令执行入口,claim 后只能协作停止,不能保证远端未执行或已经终止。配置 cancel_context 为原 op,由 executor/timer/借用引用保活,session 清理完成后才能回收。 + +保留所有原因位和第一停止原因;结果以已接受的第一原因解释。业务结束决定点锁内封存,之后的 cancel 被拒绝,不能更改终态。准备/密钥加载期间取消不可打断同步存储读取,但读取后不再获得提交资格。底层 DNS 等不可协作阻塞边界仍需说明。 + +页面只通过统一受控目标获取,状态查询 wildcard 不用于页面副作用。完整 peer 包括 server、server generation、connection generation、fd;取得引用后不再查询 current。现有 Shell 帧没有操作 ID,同一连接上先后两代 Shell 的迟到消息仍无法区分,本轮不扩协议。Exec ID 沿用原 API 权限范围,不擅自添加页面绑定或改变公开协议。 + +## 实施后核对 + +页面路径统一为 ws_handler -> handle_ssh_control -> shell_for_peer(ref++) -> 原资源 mutex / disconnect 意图 -> release。资源已结束或 I/O 失败时用原 ssh_status:error 报告,不重新选择目标。peer_closed 与客户端登记清理均传递完整 peer;修复旧 fd 关闭回调可能关闭替换连接的同类路径。 + +Exec API 直接执行 exact-ID 取消登记,去掉 is_running 预检查,并保留完整 uint32 ID。业务结束锁内封存,不等到投递结束才拒绝取消。MATCH 明确原因还修正了首次提取停止被旧共享标记误分类为超时;匹配触发规则保持原样。非用户原因时,原已匹配事实对 deadline 返回值的结果解释仍保留,详见 README。 + +原状态机的输出准入/两阶段终态/引用回收没有迁移到另一套机制。新增控制状态同样归 s_op_lock;资源 I/O 和 JSON 不进入该锁。没有引入 op-lock -> 资源 mutex 的嵌套;资源 mutex 内读取 op 状态时只取得短时 op 锁。 diff --git a/docs/repair/ws-control/control-tests.txt b/docs/repair/ws-control/control-tests.txt new file mode 100644 index 0000000..4a2046f --- /dev/null +++ b/docs/repair/ws-control/control-tests.txt @@ -0,0 +1,5 @@ +PASS actual WS controls: all four foreign controls rejected, owner controls work; borrowed original pinned, fd/epoch/server reuse and late close isolated; owner stop drains +PASS accepted cancellation persists through task/key/create/connect/auth; cancel/submit claim both orders and result freeze tested; duplicate/old/zero IDs isolated +PASS USER/TIMEOUT/MATCH keep distinct results; service stop busy does not cancel business, accepted user intent survives stop retry and all resource ledgers drain +PASS output failure seals observation without cancelling business; later explicit cancel still reaches original executor without rewriting terminal; earlier timeout retains reason +PASS actual ssh.cancel API exact-ID validation and accepted-intent response; ended operations reject without wildcard control diff --git a/docs/repair/ws-control/current-v1.txt b/docs/repair/ws-control/current-v1.txt new file mode 100644 index 0000000..abad52b --- /dev/null +++ b/docs/repair/ws-control/current-v1.txt @@ -0,0 +1 @@ +v1 business_contract=PASS diff --git a/docs/repair/ws-control/current-v2.txt b/docs/repair/ws-control/current-v2.txt new file mode 100644 index 0000000..5a3ce31 --- /dev/null +++ b/docs/repair/ws-control/current-v2.txt @@ -0,0 +1 @@ +v2 business_contract=PASS diff --git a/docs/repair/ws-control/diff-check.txt b/docs/repair/ws-control/diff-check.txt new file mode 100644 index 0000000..ab195e3 --- /dev/null +++ b/docs/repair/ws-control/diff-check.txt @@ -0,0 +1 @@ +PASS git diff --check for tracked production/test changes diff --git a/docs/repair/ws-control/f1-f2-tests.txt b/docs/repair/ws-control/f1-f2-tests.txt new file mode 100644 index 0000000..854d7e5 --- /dev/null +++ b/docs/repair/ws-control/f1-f2-tests.txt @@ -0,0 +1,23 @@ +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F2: protection transition survives ordinary log saturation +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS original peer and operation identity isolation across reconnect +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-control/historical-f1-f2.txt b/docs/repair/ws-control/historical-f1-f2.txt new file mode 100644 index 0000000..1b6c5eb --- /dev/null +++ b/docs/repair/ws-control/historical-f1-f2.txt @@ -0,0 +1,4 @@ +Frozen production snapshot hashes verified +F1 assertion: accepted SSH output enqueue failure reaches session and error frame: FAIL (stream still normal / no error frame) +F2 assertion: protection transition survives ordinary log pool saturation: FAIL (no protection frame) +CONFIRMED: both failures are behavioral assertions, not compilation or cleanup failures diff --git a/docs/repair/ws-control/historical-g1-g2.txt b/docs/repair/ws-control/historical-g1-g2.txt new file mode 100644 index 0000000..013fb9c --- /dev/null +++ b/docs/repair/ws-control/historical-g1-g2.txt @@ -0,0 +1,4 @@ +Frozen production source and original tests SHA256 verified +G1 complete production unit: replacement=2 old=1 replacement_corrupted=1 +G2 complete production unit: terminal_before_late_output=1 +CONFIRMED G1/G2 are business assertion failures in the complete frozen WS unit, not compile/dependency/cleanup failures diff --git a/docs/repair/ws-control/host-tests.txt b/docs/repair/ws-control/host-tests.txt new file mode 100644 index 0000000..88ff604 --- /dev/null +++ b/docs/repair/ws-control/host-tests.txt @@ -0,0 +1,23 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-control/operation-tests.txt b/docs/repair/ws-control/operation-tests.txt new file mode 100644 index 0000000..b6d8772 --- /dev/null +++ b/docs/repair/ws-control/operation-tests.txt @@ -0,0 +1,2 @@ +PASS 16 failure schedules: encode/SDK/socket/stale peer, early/deferred done, duplicate tokens do not double-settle +PASS production operation/TX: 36 barrier schedules, ticket/target ledgers and B09 executor retention; destroyed=36 diff --git a/docs/repair/ws-control/publication-adapter.txt b/docs/repair/ws-control/publication-adapter.txt new file mode 100644 index 0000000..7febc5e --- /dev/null +++ b/docs/repair/ws-control/publication-adapter.txt @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=84 diff --git a/docs/repair/ws-control/publication-control.txt b/docs/repair/ws-control/publication-control.txt new file mode 100644 index 0000000..4a2046f --- /dev/null +++ b/docs/repair/ws-control/publication-control.txt @@ -0,0 +1,5 @@ +PASS actual WS controls: all four foreign controls rejected, owner controls work; borrowed original pinned, fd/epoch/server reuse and late close isolated; owner stop drains +PASS accepted cancellation persists through task/key/create/connect/auth; cancel/submit claim both orders and result freeze tested; duplicate/old/zero IDs isolated +PASS USER/TIMEOUT/MATCH keep distinct results; service stop busy does not cancel business, accepted user intent survives stop retry and all resource ledgers drain +PASS output failure seals observation without cancelling business; later explicit cancel still reaches original executor without rewriting terminal; earlier timeout retains reason +PASS actual ssh.cancel API exact-ID validation and accepted-intent response; ended operations reject without wildcard control diff --git a/docs/repair/ws-control/publication-f1f2.txt b/docs/repair/ws-control/publication-f1f2.txt new file mode 100644 index 0000000..854d7e5 --- /dev/null +++ b/docs/repair/ws-control/publication-f1f2.txt @@ -0,0 +1,23 @@ +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F2: protection transition survives ordinary log saturation +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS original peer and operation identity isolation across reconnect +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-control/publication-gate.md b/docs/repair/ws-control/publication-gate.md new file mode 100644 index 0000000..1d37d7c --- /dev/null +++ b/docs/repair/ws-control/publication-gate.md @@ -0,0 +1,13 @@ +# PR #42 更新前检查 + +结论:**可以推送**。用户已明确授权追加提交到 Fork 并更新现有 PR;不合并、不发布、不操作设备。 + +发布前本地、Fork 分支及 PR head 一致为 1591ecc8e293c0fa62feda18d2517edfc179ca5a。范围为 changes.json 的 11 个生产/测试文件及本目录记录,排除 output/、tmp/ 和另一份未跟踪 runtime reviewer diff-check。 + +已重新检查统一 peer 目标获取、持引用执行、旧连接关闭、exact-ID 取消、取消/提交的同锁决定点、原因区分、结束封存,以及实际 WS/API/前端消息接收路径;没有发现阻止发布供审查的问题。未承诺穷尽双核交错。 + +本次重新执行并通过:run_control.sh、run_operation_adapter.sh、run_reviewer.sh、run_f1_f2.sh 和 npm --prefix tests/prompts test,日志为 publication-*.txt;git diff --check 通过。主机 C 使用固定 IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf。 + +逐文件确认生产/测试/patch 哈希与 changes.json 一致,实际 app/www/sdkconfig 与 build-artifacts.json 一致。完整 SDK 编译、其他主机及 Chrome 套件沿用同一源码快照实施阶段的实际记录,本次发布前未重复运行。原始工具输出、冻结文件及 patch 保留原有空格,不把证据格式告警当作生产代码问题。 + +仍需真实设备验证取消/断网/双核/资源水位;同一连接不同 Shell 代次缺少操作 ID、同步密钥读取/DNS 不可即时中止等边界见 README。changes.json 的 local-only scope 和 working-tree-status.txt 是实施阶段历史快照,后续发布以本次用户授权为准。新增 C 回归未接入 CI,最新 PR CI 必须单独查看。 diff --git a/docs/repair/ws-control/publication-reviewer.txt b/docs/repair/ws-control/publication-reviewer.txt new file mode 100644 index 0000000..5a5cfbd --- /dev/null +++ b/docs/repair/ws-control/publication-reviewer.txt @@ -0,0 +1,15 @@ +PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds +PASS HTTPD barrier timeout retains worker and retry state +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-control/publication-webui.txt b/docs/repair/ws-control/publication-webui.txt new file mode 100644 index 0000000..5202cba --- /dev/null +++ b/docs/repair/ws-control/publication-webui.txt @@ -0,0 +1,51 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (16.180958ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.253084ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (7.53525ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.558875ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.658583ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.761917ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (6.055125ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.430375ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.813208ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.916709ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.858541ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.158375ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.905584ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.182ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.813583ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.630667ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.566208ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.103959ms) +✔ en-US: batch deletion all / partial / no success with business errors (6.277958ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.795458ms) +✔ en-US: file names are text; upload/verification/apply remain separate (6.100709ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (8.308292ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.614541ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (4.520667ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.875291ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.713208ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (5.025125ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (6.049375ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (5.303375ms) +✔ en-US: upload and download aggregates cover all success and all failure (5.2035ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (4.989417ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.736958ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.6405ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.680459ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.791458ms) +✔ en-US: unknown stop result never escalates to forced termination (4.568625ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (6.09925ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.112417ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 255.366083 diff --git a/docs/repair/ws-control/resources.txt b/docs/repair/ws-control/resources.txt new file mode 100644 index 0000000..ac48c80 --- /dev/null +++ b/docs/repair/ws-control/resources.txt @@ -0,0 +1,300 @@ +ts_ws_operation.c +00000000 00000001 b s_op_accepting +00000000 00000001 b s_op_tick +00000000 00000007 T ts_ws_op_id +00000000 00000008 b s_op_delivery +00000000 00000008 d s_op_lock +00000000 00000008 b s_op_sequence +00000000 0000000e r __func__$0 +00000000 0000000e r __func__$1 +00000000 0000000e r __func__$9 +00000000 00000010 r __func__$8 +00000000 00000010 R op_sizes +00000000 00000011 r __func__$4 +00000000 00000011 r __func__$7 +00000000 00000011 T ts_ws_op_shell_owner +00000000 00000012 T ts_ws_op_peer +00000000 00000015 t fail_locked +00000000 00000016 r __func__$3 +00000000 00000017 r __func__$2 +00000000 00000017 r __func__$5 +00000000 00000017 r __func__$6 +00000000 0000001c T ts_ws_op_data +00000000 0000001c T ts_ws_op_set_maintenance +00000000 0000001e T ts_ws_op_shell_connection +00000000 0000001e T ts_ws_op_shell_control +00000000 0000001f T ts_ws_op_needs_tick +00000000 00000022 T ts_ws_op_cancelled +00000000 00000022 T ts_ws_op_enable +00000000 00000022 T ts_ws_op_executing +00000000 00000022 T ts_ws_op_stop_admission +00000000 00000023 T ts_ws_op_starting +00000000 00000024 t close_locked +00000000 00000024 T ts_ws_op_is_open +00000000 00000026 T ts_ws_op_request_stop +00000000 00000030 T ts_ws_op_close_begin +00000000 00000032 t close_snapshot +00000000 00000032 T ts_ws_op_business_running +00000000 00000033 T ts_ws_op_open +00000000 00000034 t request_stop_locked +00000000 00000034 T ts_ws_op_retain +00000000 00000034 T ts_ws_op_stats +00000000 0000003a T ts_ws_op_bind +00000000 0000003b T ts_ws_op_business_end +00000000 0000003b T ts_ws_op_claim_submit +00000000 0000003c T ts_ws_op_executor_take +00000000 0000003c T ts_ws_op_release +00000000 00000040 T ts_ws_op_busy +00000000 00000044 T ts_ws_op_executor_done +00000000 0000004a t fallback +00000000 0000006e T ts_ws_op_cancel_exec +00000000 00000070 T ts_ws_op_discard +00000000 0000007e t shell_for_peer +00000000 0000007e T ts_ws_op_acquire +00000000 00000086 T ts_ws_op_close_finish +00000000 00000088 T ts_ws_op_output_begin +00000000 00000157 T ts_ws_op_create +00000000 0000018e t settle_target +00000000 00000202 T ts_ws_op_output_finish +00000000 000004f8 T ts_ws_op_poll +00000000 00000760 b s_ops + + +/tmp/tianshan-control-build/resources/ts_ws_operation.c.o: file format elf32-xtensa-le + +Contents of section .rodata.op_sizes: + 0000 b0030000 18010000 10000000 58000000 ............X... + +/tmp/tianshan-control-build/resources/ts_ws_operation.c:92:13:close_locked 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:115:13:fail_locked 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:241:13:request_stop_locked 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:96:13:close_snapshot 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:225:27:shell_for_peer 96 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:33:6:ts_ws_op_enable 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:34:6:ts_ws_op_stop_admission 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:35:6:ts_ws_op_busy 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:56:6:ts_ws_op_bind 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:59:6:ts_ws_op_set_maintenance 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:60:6:ts_ws_op_needs_tick 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:61:7:ts_ws_op_data 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:62:10:ts_ws_op_id 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:104:13:fallback 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:63:14:ts_ws_op_peer 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:64:20:ts_ws_op_acquire 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:70:6:ts_ws_op_retain 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:71:6:ts_ws_op_release 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:74:6:ts_ws_op_executor_take 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:77:6:ts_ws_op_executor_done 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:80:6:ts_ws_op_executing 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:81:6:ts_ws_op_open 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:84:6:ts_ws_op_is_open 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:85:6:ts_ws_op_starting 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:86:6:ts_ws_op_discard 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:40:20:ts_ws_op_create 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:100:6:ts_ws_op_close_begin 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:110:6:ts_ws_op_close_finish 288 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:118:13:settle_target 48 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:140:6:ts_ws_op_output_begin 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:149:6:ts_ws_op_output_finish 176 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:175:6:ts_ws_op_poll 576 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:221:6:ts_ws_op_stats 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:232:20:ts_ws_op_shell_control 80 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:235:20:ts_ws_op_shell_connection 80 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:238:20:ts_ws_op_shell_owner 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:247:20:ts_ws_op_cancel_exec 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:254:6:ts_ws_op_request_stop 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:257:6:ts_ws_op_cancelled 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:260:6:ts_ws_op_claim_submit 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:266:21:ts_ws_op_business_end 32 static +/tmp/tianshan-control-build/resources/ts_ws_operation.c:274:6:ts_ws_op_business_running 32 static + +ts_webui_ws.c +00000000 00000001 b s_log_streaming_enabled +00000000 00000001 b s_ws_stopping +00000000 00000004 b s_log_callback_handle +00000000 00000004 b s_output_mutex +00000000 00000004 b s_power_event_handle +00000000 00000004 b s_server +00000000 00000004 d s_terminal_client_fd +00000000 00000004 b s_terminal_mutex +00000000 00000004 b s_terminal_output_buf +00000000 00000004 b s_terminal_output_len +00000000 0000000d r __func__$0 +00000000 0000000e r __func__$1 +00000000 00000014 R adapter_sizes +00000000 00000018 r s_level_names +00000000 0000001a t exec_timer_drained +00000000 00000022 T ts_webui_ssh_exec_start +00000000 00000023 t ssh_cleanup +00000000 00000028 t exec_abort +00000000 0000002b T ts_webui_ssh_result_free +00000000 0000002c t ssh_disconnecting +00000000 0000002c T ts_webui_ssh_exec_is_running +00000000 0000002f T ts_webui_ws_stopped +00000000 00000031 T ts_webui_ssh_exec_cancel +00000000 00000032 t shell_destroy +00000000 00000035 T ts_webui_broadcast +00000000 00000042 t shell_resources_close +00000000 00000045 t power_state_to_string +00000000 0000004a t has_log_clients +00000000 0000004c t update_log_stream_state +00000000 00000050 t ssh_exec_timeout_callback +00000000 0000005c t peer_closed +00000000 0000005f t exec_retry_timer_drain +00000000 0000006c T ts_webui_log_stream_enable +00000000 00000078 t ssh_close +00000000 0000007e T ts_webui_ssh_exec_start_ex +00000000 00000089 T ts_webui_broadcast_event +00000000 0000009c t terminal_output_cb +00000000 000000aa t exec_destroy +00000000 000000ac t ssh_request_error +00000000 000000b5 t ssh_start_status +00000000 000000ca t ssh_poll_task +00000000 000000cc t ssh_send_output +00000000 000000db t add_client +00000000 000000ee t set_client_role +00000000 00000122 t exec_maintenance +00000000 0000013a t cleanup_disconnected_client +00000000 00000146 T ts_webui_ws_stop +00000000 00000158 t log_ws_callback +00000000 00000163 t power_policy_event_handler +00000000 00000178 t simple_pattern_match +00000000 00000198 t handle_ssh_control +00000000 000001c0 b s_clients +00000000 00000214 t handle_terminal_command +00000000 00000246 T ts_webui_ws_init +00000000 00000270 t start_terminal_session +00000000 000002b2 t handle_ssh_connect +00000000 0000050d t ts_webui_ssh_exec_start_ex_impl +00000000 0000065c t ssh_exec_output_callback +00000000 00000a4e t ws_handler +00000000 00000c07 t ssh_exec_task + + +/tmp/tianshan-control-build/resources/ts_webui_ws.c.o: file format elf32-xtensa-le + +Contents of section .rodata.adapter_sizes: + 0000 14000000 18030000 88000000 38000000 ............8... + 0010 20000000 ... + +/tmp/tianshan-control-build/resources/ts_webui_ws.c:124:20:power_state_to_string 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1177:13:has_log_clients 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:137:13:power_policy_event_handler 736 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:180:13:ssh_request_error 48 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:381:18:add_client 96 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:357:13:terminal_output_cb 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:400:13:handle_terminal_command 64 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:217:13:ssh_send_output 320 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:200:13:shell_destroy 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1579:13:exec_destroy 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:234:18:ssh_start_status 80 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:208:13:ssh_close 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:248:13:ssh_disconnecting 320 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:193:13:shell_resources_close 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:255:13:ssh_poll_task 2096 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:324:13:handle_ssh_control 64 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1540:13:exec_timer_drained 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1570:13:exec_retry_timer_drain 48 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:275:13:ssh_cleanup 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1057:6:ts_webui_ws_stopped 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1112:13:log_ws_callback 48 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1316:13:exec_abort 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1531:13:ssh_exec_timeout_callback 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1240:13:simple_pattern_match 48 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1591:13:ssh_exec_task 544 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1323:13:ssh_exec_output_callback 1088 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1546:13:exec_maintenance 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1976:18:ts_webui_ssh_exec_start_ex_impl 528 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:928:11:ts_webui_ws_init 64 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1064:11:ts_webui_broadcast 48 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1077:11:ts_webui_broadcast_event 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1154:11:ts_webui_log_stream_enable 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1190:13:update_log_stream_state 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:574:13:cleanup_disconnected_client 128 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:610:13:peer_closed 64 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:110:13:set_client_role 128 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:483:13:start_terminal_session 128 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:282:13:handle_ssh_connect 208 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:618:18:ws_handler 176 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:1021:11:ts_webui_ws_stop 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:2170:11:ts_webui_ssh_exec_start_ex 144 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:2185:11:ts_webui_ssh_exec_start 48 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:2192:6:ts_webui_ssh_result_free 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:2201:11:ts_webui_ssh_exec_cancel 32 static +/tmp/tianshan-control-build/resources/ts_webui_ws.c:2211:6:ts_webui_ssh_exec_is_running 32 static + +ts_ws_subscriptions.c +00000000 00000001 b s_stop_owner +00000000 00000004 b s_entries +00000000 00000004 b s_outstanding +00000000 00000004 b s_state +00000000 00000004 b s_subscription_cursor +00000000 00000004 b s_topic_cursor +00000000 00000004 b s_worker +00000000 00000008 b s_allocation_retry_at +00000000 00000008 d s_lock +00000000 00000008 b s_sequence +00000000 0000000c b s_handlers +00000000 0000001a t wake_locked +00000000 0000001c r fields +00000000 0000001c r metrics +00000000 0000001f T ts_ws_subscriptions_wake +00000000 00000028 t leave +00000000 00000035 t after_ms +00000000 00000037 t enter +00000000 00000038 t topic_id +00000000 0000003a T ts_ws_subscriptions_in_context +00000000 0000003d t metric_needed +00000000 00000042 t wait_ticks +00000000 00000047 t find_revision +00000000 0000004e t delivery_valid +00000000 0000006a t ts_ws_json_reference +00000000 00000079 t reserve +00000000 0000007a T ts_ws_subscriptions_pause +00000000 0000007b T ts_ws_client_disconnected +00000000 00000084 r topics +00000000 00000096 t telemetry_worker +00000000 000000a6 t submit +00000000 000000c1 T ts_ws_unsubscribe +00000000 000000c8 t delivery_done +00000000 000000ce t event_handler +00000000 000000e6 T ts_ws_subscriptions_drain +00000000 000000f0 T ts_ws_subscriptions_init +00000000 00000128 b s_stats +00000000 000001b4 T ts_ws_broadcast_to_topic +00000000 000001d3 T ts_ws_subscriptions_deinit +00000000 00000209 t next_wait +00000000 000002e5 T ts_ws_subscribe +00000000 00000305 t collect_batch +00000000 00000460 b s_events +00000000 00000548 t run_batch +00000000 00000a00 b s_subs + +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:70:16:after_ms 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:97:24:find_revision 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:273:19:wait_ticks 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:103:13:delivery_valid 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:144:13:metric_needed 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:85:13:enter 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:75:13:wake_locked 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:128:13:reserve 80 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:93:13:leave 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:111:13:delivery_done 48 static +/Users/massif/TianshanOS/components/ts_webui/include/ts_ws_transport.h:65:20:ts_ws_json_reference 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:150:13:collect_batch 176 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:136:13:submit 96 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:198:13:run_batch 3360 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:281:19:next_wait 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:301:13:telemetry_worker 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:80:12:topic_id 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:76:6:ts_ws_subscriptions_wake 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:353:11:ts_ws_subscriptions_pause 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:366:11:ts_ws_subscriptions_drain 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:386:11:ts_ws_subscriptions_deinit 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:332:11:ts_ws_subscriptions_init 96 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:419:11:ts_ws_subscribe 144 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:453:11:ts_ws_unsubscribe 96 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:464:6:ts_ws_client_disconnected 96 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:470:6:ts_ws_broadcast_to_topic 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:317:13:event_handler 32 static +/tmp/tianshan-control-build/resources/ts_ws_subscriptions.c:495:6:ts_ws_subscriptions_in_context 32 static diff --git a/docs/repair/ws-control/reviewer-tests.txt b/docs/repair/ws-control/reviewer-tests.txt new file mode 100644 index 0000000..5a5cfbd --- /dev/null +++ b/docs/repair/ws-control/reviewer-tests.txt @@ -0,0 +1,15 @@ +PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds +PASS HTTPD barrier timeout retains worker and retry state +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-control/runtime-tests.txt b/docs/repair/ws-control/runtime-tests.txt new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ws-control/runtime-tests.txt @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ws-control/webui-browser-tests.txt b/docs/repair/ws-control/webui-browser-tests.txt new file mode 100644 index 0000000..24b8315 --- /dev/null +++ b/docs/repair/ws-control/webui-browser-tests.txt @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (1878.702667ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (709.276333ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (291.23575ms) +✔ en-US: initial language failure blocks controls and retry recovers (369.070708ms) +✔ delayed language package and rapid switches keep the latest requested language (280.668792ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (468.180917ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (306.375916ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (454.483375ms) +✔ initial delayed language keeps controls inert until the real package arrives (239.382541ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (341.336625ms) +✔ terminal can initialize after failed resource load using newly served resources (415.50275ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (1108.079583ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (261.506375ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (360.457375ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (449.429541ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (459.24925ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (556.892917ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (235.944375ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (186.419042ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (171.891ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (171.117958ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (222.181458ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (179.048625ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (282.824625ms) +✔ R3: late validation cannot revive an old apply entry en-US (245.548ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (259.613709ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (232.205792ms) +✔ R6: fixed upload destination and separate refresh failure en-US (241.750334ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (255.059375ms) +✔ R2: authenticated startup initializes once (325.448ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (323.758333ms) +✔ R4/R5: newest result wins over late success and late failure (251.516416ms) +✔ R3: overlapping writes to one path cannot claim current verified content (256.3915ms) +✔ R2: disposed page only removes its dashboard callback (257.151958ms) +✔ R2: stale finally cannot unlock the new page read (249.5035ms) +✔ R1: delayed sign-out does not clear a newer sign-in (242.441125ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (302.310042ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (373.90225ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 8829.386583 diff --git a/docs/repair/ws-control/webui-node-tests.txt b/docs/repair/ws-control/webui-node-tests.txt new file mode 100644 index 0000000..7d370c7 --- /dev/null +++ b/docs/repair/ws-control/webui-node-tests.txt @@ -0,0 +1,51 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (15.817291ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (7.170833ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (7.866792ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.68625ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.991917ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (4.93225ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (5.917958ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (6.135541ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.658166ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (4.775875ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.605166ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.881083ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.772042ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.284792ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.914291ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.485792ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.652ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.955583ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.939167ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.73875ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.750417ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (7.9005ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.623125ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (4.67675ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.516958ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.232042ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (4.899125ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (5.904542ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.838083ms) +✔ en-US: upload and download aggregates cover all success and all failure (5.374792ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (5.008375ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.757708ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.768291ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.949166ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.905042ms) +✔ en-US: unknown stop result never escalates to forced termination (4.328334ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.718584ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.095375ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 255.688959 diff --git a/docs/repair/ws-control/working-tree-status.txt b/docs/repair/ws-control/working-tree-status.txt new file mode 100644 index 0000000..4e4bff0 --- /dev/null +++ b/docs/repair/ws-control/working-tree-status.txt @@ -0,0 +1,15 @@ + M components/ts_api/src/ts_api_ssh.c + M components/ts_webui/include/ts_ws_operation.h + M components/ts_webui/src/ts_webui_ws.c + M components/ts_webui/src/ts_ws_operation.c + M components/ts_webui/web/js/lang/en-US.js + M components/ts_webui/web/js/lang/zh-CN.js + M tests/prompts/regression.test.cjs + M tests/ws_subscriptions/test_operation_adapter.c +?? docs/repair/ws-control/ +?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt +?? output/ +?? tests/ws_subscriptions/replay_control_baseline.py +?? tests/ws_subscriptions/run_control.sh +?? tests/ws_subscriptions/test_control.c +?? tmp/ diff --git a/docs/repair/ws-f1-f2/README.md b/docs/repair/ws-f1-f2/README.md new file mode 100644 index 0000000..d04f892 --- /dev/null +++ b/docs/repair/ws-f1-f2/README.md @@ -0,0 +1,101 @@ +# PR #42:F1/F2 本地修复与验证(2026-09-25) + +本轮以 `bb0958c902d37ddc2b2deb36291b5439c0964160`、分支 `fix/v0.5.2-reliability-and-prompts` 的真实工作区为基线。F1/F2 在冻结生产源码上的业务反例成立,当前源码通过相同断言及交叉回归。现有 R1—R5 回归保留并通过。**这是本地验证结论,不是实机验收或发布许可。** + +没有连接设备、刷机、重启、执行远端命令、修改保护动作/SSH 匹配规则/前端布局/外部消息类型与字段/版本/发布流程,也没有提交、推送、更新 PR、合并或发布。原未跟踪的 `output/`、`tmp/` 和其他修复记录保留。 + +## 基线和反例 + +- `baseline.json`:开始修复时的 HEAD、分支、git status、逐文件 SHA-256。 +- `pre-fix-source.tar.gz`:当时相关 components、主机回归和核心入口的真实源码,不是事后另写的缺陷副本。 +- `bash tests/ws_subscriptions/run_f1_f2.sh --baseline`:解包到临时目录并核对哈希,使用相同 F1/F2 断言对冻结生产 C 重放。该命令退出 0 表示确认旧行为失败;编译错误、ASan 或夹具清理错误不能充当反例。见 `before.txt`。 +- `bash tests/ws_subscriptions/run_f1_f2.sh`:同样两条断言在当前源码通过,并执行下面的交叉场景。见 `after.txt`。 +- 本轮没有收到另行提到的外部审查报告/反例包;依据用户给出的 F1/F2 要求,直接在上述源码建立反例。 + +| 缺陷 | 冻结源码证据 | 当前行为 | +|---|---|---| +| F1 普通 SSH 输出接受后静默丢失 | HTTPD 入队失败后仍维持正常流状态,没有错误帧 | 所属会话收到完成结算;Shell 停止该流并报告输出不完整;exec 结束网页观察并报告远端结果未确认,不自动终止或重放命令 | +| F2 日志挤掉保护通知 | 普通日志占满两个文本槽后,真实保护回调未发出 `power_event` | 真实保护回调先取得独立配额,再编码并提交;普通日志的对象、描述符和字节占用均不能消耗该配额 | + +## 生产调用链与所有权 + +### F1:分类、结算和顺序 + +消息对象明确记录 `MSG_TOPIC / MSG_ORDINARY / MSG_RESULT / MSG_POWER / MSG_POWER_TICK` 类别。`ts_ws_transport_submit()` 按消息来源选择描述符池,完成回调的有无不再改变类别。SSH 输出即使带 `done`,仍使用普通流池,不占遥测或关键结果配额。 + +本地接受返回 `ESP_OK` 后,由 transport 对每个投递执行一次 `settle()`:成功、HTTPD 入队拒绝、实际发送失败、目标失效和适用的取消路径都在这里结算。同步拒绝表示没有接受,不调用 `done`,调用方自行结算它预登记的 pending。描述符持有消息、工作与发布引用;SDK 回调早于提交返回时,发布引用仍防止槽复用和重复释放。描述符的固定 peer(server/epoch/fd/connection)、FIFO order 和流代次一起限定身份。 + +- **Shell**:`ssh_send_output → transport_submit → publish/deliver → ssh_output_done`。提交前登记 pending;异步失败标记当前代次输出不完整,停止 Shell 输出并进入既有 error 终态。旧代次通知不改变新会话。终态先写入原有 reservation,所有先前输出结算后才提交;先请求 closed、后发现输出失败时,发出 error,不能在已知缺块后显示正常结束。新会话仍受旧 producer、pending 和终态发送状态约束。 +- **exec**:真实 `ssh_exec_output_callback` 以及 started/match 通知都使用 `ssh_exec_stream_publish`。一次多目标提交先登记整个目标数,防止第一个同步完成回调提前结束整批。某目标失败时不重播已成功输出;使用原有 `ssh_exec_error` 明确说明输出不完整、远端结果未确认。一次性的 terminal claim 防止后台结束时再发正常 done。**这是结束网页观察,不是取消远端操作**;原收集、匹配、变量更新及业务取消规则不变。 +- **exec 终态**:在首次终态请求时保存原全局接收者快照,等所有先前输出结算后才发出;不因重试或 fd 复用改投替代连接。新执行不得覆盖仍在等待结算的 reservation。 +- **HTTPD 失败回调**:可以登记保留的错误终态,但结算结束前保持发送执行器 busy,之后唤醒 worker,避免失败回调递归调用 SDK 入队形成栈增长。 +- **其余调用方**:遥测仍使用订阅校验及完成回调;普通日志、console 终端与普通全局业务事件保留原有有界 best-effort 行为。本轮不宣称所有既有流式发送都变成可靠投递。Shell connecting/connected 的就绪判定和原状态协议保留。 + +前端调用链也已静态核对:`terminal.js:handleSshStatus` 在 error 时退出 SSH 模式并显示 message;`app.js` 的 `ssh_exec_error` 按 session_id 结束当前观察并展示错误详情。没有改动布局或协议。既有界面错误标题仍是通用错误提示,新增详情明确写明“输出传递不完整、远端结果未确认”,不宣称远端命令确定失败。 + +### F2:准入、事件分类和失败处理 + +真实 `power_policy_event_handler` 先快照所有有效连接并预留完整目标描述符及消息,再编码原有固定字段。保护消息采用固定缓冲,不依赖普通日志正在使用的堆分配;格式化仅使用常量字符串与数字,非有限电压仍编码为 JSON null。没有目标时不构造消息。 + +状态转换、低电压、关机开始、受保护、恢复开始/完成等使用四个保护槽。countdown_tick/debug_tick 单独使用一个周期槽,不侵占转换容量。**本轮没有合并或覆盖事件**:已接受事件保持 FIFO;第五个并发转换或第二个未排空周期事件会明确拒绝并记录 admission 日志及 `power_rejected`,不承诺无限保存。适用的同步提交失败由调用方记录,异步目标失败记录 class/fd/result 及 `power_failed`。 + +只有 SDK 明确拒绝入队、尚未尝试发送的关键描述符会保留重试。最多 **300 次入队尝试**,间隔至少 100 ms;不是精确 30 秒的墙钟期限,实际调度可能更慢。达到上限会终态结算、记录失败并释放。实际 socket 发送失败或连接失效**不重发帧**,避免不明确发送导致重复。重试仅针对一个目标,不重播整个广播批次。 + +固定 FIFO、worker 唤醒及 next-wait 负责在没有新业务消息时推进;没有新增网络等待、无限循环或保护动作。正常容量持续释放的受控竞争测试中,日志、保护通知和八个周期主题均有进展。 + +### 停止与重试 + +沿用 R1/R4:先拒绝新业务、暂停遥测,再等待 producer 和已接受结果。新增 Shell pending/终态及 exec result-active 检查,防止在输出回调还可能提交错误终态时提前关闭 transport 准入。busy/timeout 保留 worker 和依赖,允许无新消息排空后再重试。power handler 仍同步注销并排空后才停止 transport;不把注销返回简单等同于所有回调已退出。 + +## 容量预算(默认 8 连接) + +| 类别 | 消息对象 | 目标描述符 | payload 配额/上限 | 释放条件 | +|---|---:|---:|---|---| +| 遥测/原操作事件 | 6 | 32 | 每条 32 KiB;共享非保护字节预算 | 所有目标与 producer 引用释放 | +| 普通日志/SSH 输出/普通广播 | 2 | 8 | 单条小于 512 KiB;共享非保护预算 | 每目标结算后释放;不覆盖旧条目 | +| Shell/exec 关键终态 | 2 | 16 | Shell 4 KiB、exec 512 KiB 预留;共享非保护预算 | 前序输出结算后发布,或明确失败回收;目标排空后释放 | +| 保护转换 | 4 | 32 | 4 × 1024 B 固定缓冲及独立字节配额 | 所有目标结算后可复用 | +| 保护周期/调试事件 | 1 | 8 | 1024 B 固定缓冲及独立字节配额 | 所有目标结算后可复用 | + +共 15 个消息对象、96 个目标描述符;传输 payload 总上限仍为 **1 MiB**。其中保护独占 5 KiB,其他类别合计最多 1 MiB − 5 KiB。这意味着非保护消息的可用预算比此前少 5 KiB,原“两个最大文本帧同时占满总预算”的测试已调整为新边界,未降低无预算不采集的断言。 + +保护缓冲 **5 KiB 常驻**,不是按需堆分配。目标编译器测得描述符表 8448 B(原 4480 B)、消息控制表 300 B(原 160 B)、exec 接收者快照 256 B;另有少量计数/原子状态。原输出 cJSON、业务缓存及 SDK 自身内存不计入 transport payload 上限,本轮不声称全固件总内存被此上限覆盖。 + +目标编译器单函数栈帧:power callback 736 B、exec output callback 528 B、run_batch 3360 B;详见 `resources.txt`。这些数字不是完整调用链峰值,也不是 ESP32 实测栈水位。worker 数量、栈配置和硬件采样频率未变。 + +## 本轮实际验证 + +| 层级 | 命令 | 结果和证据 | +|---|---|---| +| 冻结生产反例 | `bash tests/ws_subscriptions/run_f1_f2.sh --baseline` | 两条旧行为失败已确认;`before.txt` | +| 当前生产 C 与调用方 | `bash tests/ws_subscriptions/run_f1_f2.sh` | 相同断言及交叉场景通过;`after.txt` | +| 既有 WS | `bash tests/ws_subscriptions/run_host.sh` | 通过;`host.txt` | +| R1—R5 | `bash tests/ws_subscriptions/run_reviewer.sh` | 通过;`reviewer.txt` | +| 运行时 | `bash tests/runtime/run_all.sh` | 本轮重跑通过;`runtime.txt` | +| 证书/HTTPS | `bash tests/certificate/run_host.sh` | 本轮重跑通过;`certificate.txt`;其中 REPRODUCED 是该套件自己的固定旧版反例 | +| WebUI Node | `npm test --prefix tests/prompts` | 本轮重跑通过;`prompts.txt` | +| Chrome 浏览器 | `npm run test:browser --prefix tests/prompts` | 本轮中英文回归通过;`browser.txt`;沙箱内启动失败,获工具批准后用临时 Chrome 配置在沙箱外重跑;后端模拟 | +| ESP32-S3 编译/链接 | 固定 ESP-IDF v5.5.2:`idf.py -B /tmp/tianshan-ws-build/build -D SDKCONFIG=/tmp/tianshan-ws-build/sdkconfig build` | 本轮通过,应用 `0x213f70`,分区余 31%;`build.txt` | +| 静态检查 | `git diff --check`、完整调用链复核 | 通过;`diff-check.txt`。本轮 diff 文件与新建测试另外列入 `changes.patch` | + +构建前设置 `DEVELOPER_DIR=/Library/Developer/CommandLineTools`、使用本地 idf5.5 Python 环境并 source SDK `export.sh`。构建日志中 flash 命令是 SDK 的提示,**没有执行**。首次目标编译发现事件 ID 日志格式类型不符,已改为显式 long 后重建通过;未将失败构建当作验证成功。 + +交叉测试明确覆盖:首次/稍后 HTTPD 入队失败、closed 先提出后发现丢块、旧 peer/fd 复用、新会话准入隔离与迟到旧代次通知、回调早于提交返回、实际 socket 失败、逐目标结算次数、exec 部分失败无重复、持续 exec 的及时错误提示、三类容量竞争、保护容量超载与事件 FIFO、300 次拒绝上限、busy/timeout 后无新消息排空、遥测取消不误取消普通输出,以及日志/保护/八主题持续竞争。 + +测试编译完整生产 transport/manager,并从当前文件提取完整 Shell、exec 输出回调/发送/终态、保护事件函数体;SDK cJSON 为真实库。SDK 网络、设备、时钟和 RTOS 由边界替身控制。代次测试包含实际 fd 重用/准入过程,并额外注入迟到旧回调以验证 guard;不是 ESP32 真实线程调度证明。 + +## 独立自查与残余验收 + +自查范围覆盖生产者 → 准入/预留 → 本地 FIFO → SDK 入队 → 实际 send 返回 → 完成回调 → 流状态/终态 → 上层停止及重试,也核对真实前端 error 消费路径。没有仅凭辅助函数、数量或 CI 判定通过;本轮未运行或更新 CI。 + +本地证据关闭的是 F1 的接受后无反馈路径和 F2 的日志争抢保护配额路径。既有兼容性回归通过。仍需另行授权的设备验收包括: + +1. 真实 HTTPD 控制队列拥塞、慢 TCP/RST/LRU、多标签页与 fd 重用下的最终可见提示和无重复接收。 +2. ESP32 双核并发中 producer 收尾、最后输出回调与停止重试交错,验证堆/描述符回收及完整调用链栈水位。 +3. 保护状态转换密集出现时的 FIFO、周期槽拒绝和失败日志;核对原硬件保护动作及时间顺序未受网络负载影响。 +4. 长时间混合日志、SSH 输出和八主题竞争时的内存、延迟和实际进展;验证 5 KiB 常驻缓冲及减少的非保护预算是否满足设备负载。 +5. SSH 网页观察因输出失败结束后,真实远端任务仍按原业务规则运行/结束;不能把网页 error 当作远端取消或执行失败的确认。 + +已经向 SDK 提交不等于浏览器确认收到。socket 失败、断线、持续超过有限容量或持续拒绝入队时仍可能无法送达,系统给出失败计数/日志并回收,不承诺无损无限队列。`/ws` 既有独立认证/主题授权缺口亦未在本轮修复。 + +`final-manifest.json` 记录最终源码、证据和本地构建哈希;`changes.patch` 是相对本轮基线的代码、测试差异。后续 CI 接入建议见 `tests/ws_subscriptions/README.md`,本轮没有改动工作流。 diff --git a/docs/repair/ws-f1-f2/after.txt b/docs/repair/ws-f1-f2/after.txt new file mode 100644 index 0000000..6d212e3 --- /dev/null +++ b/docs/repair/ws-f1-f2/after.txt @@ -0,0 +1,23 @@ +F1 assertion: accepted SSH output enqueue failure reaches session and error frame: PASS +F2 assertion: protection transition survives ordinary log pool saturation: PASS +PASS late SSH rejection: prior output settles before terminal; closed becomes explicit incomplete-output error +PASS callback-before-return and actual send failure: exactly one settlement, no reference leak +PASS old connection/generation cannot receive old output or fail replacement session +PASS actual exec callback: partial target failure is independent; no successful output replay and no false done +PASS continuous exec: observation reports incomplete immediately; no remote abort/replay or later normal completion +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS busy stop retains output and protection drain; retry releases dependencies +PASS timeout stop continues output/protection drain without new messages; retry completes +PASS completion callbacks do not reclassify SSH output or subject it to telemetry cancellation +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-f1-f2/baseline.json b/docs/repair/ws-f1-f2/baseline.json new file mode 100644 index 0000000..577ce6b --- /dev/null +++ b/docs/repair/ws-f1-f2/baseline.json @@ -0,0 +1,96 @@ +{ + "head": "bb0958c902d37ddc2b2deb36291b5439c0964160", + "branch": "fix/v0.5.2-reliability-and-prompts", + "status": "?? docs/repair/ws-f1-f2/\n?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt\n?? output/\n?? tmp/\n", + "sha256": { + "components/ts_webui/CMakeLists.txt": "9a52c046ca47d6e19fa001796ed7469387566e4cfb176a85d55a5f1b96f2fcfa", + "components/ts_webui/Kconfig": "6a1fc77d34f7c635b44a922f4c7c9fb96832a9f6bb433967c26e3bdc451ae286", + "components/ts_webui/web/favicon.ico": "1ea04b690d7fe816da5efb405c13f9cd953366026eb3553e214de8d5df0d3648", + "components/ts_webui/web/index.html": "0b3ce77c7da2da7d18bd086dfe55fc33e994adbfe06f2f47eb6d69c01fe6124a", + "components/ts_webui/include/ts_ws_subscriptions.h": "ab44ae214761c059ceebb993c61fa1ee8c0a8bc2b1a9b1bb19f864ea4dc534ea", + "components/ts_webui/include/ts_ws_transport.h": "f69df08ce9f21b89a00f6e8d7d74ec1430567053c46a150961f61bc8d20f9ec2", + "components/ts_webui/include/ts_webui.h": "374e230b4f0d016adb2373acd2e6431cf537eaeb8f7f84efcf53523d6dad0402", + "components/ts_webui/src/ts_webui_ws.c": "425e52b9eec4924c005c18f5bd3c182c50eba1722a21d9266615bc7026db36f7", + "components/ts_webui/src/ts_ws_transport.c": "8cafd0c9313f5e07fff574a40292df599d73d695c00f3290a1573e0dbcd2166c", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_api.c": "c8225f3fc36be3446947e205932a3d43340665d687b81c23c16556f3be8dc9b8", + "components/ts_webui/src/ts_ws_subscriptions.c": "0782ccc9b76356d2a358e837a8f8cfa20f6aeb8f88b0f720d0ca0f037f4d5472", + "components/ts_webui/web/css/style.css": "30dab8799ed2a8b0a5da49ec84202b30f3c951779ea4533e847a53b2ac9b8dff", + "components/ts_webui/web/images/tslogo-32.png": "64e4bce72f2b13c81bef5b46ae919abeeb47f98571cf5e55460385880731810b", + "components/ts_webui/web/images/tslogo-512.png": "b7508585c46e16fcc7d42c52459ab55df32716aea85a10a560cd64de7cceb8e8", + "components/ts_webui/web/images/tslogo-128.png": "f09ac97789726872277a0399338cd9bfd0493752de930aeb6b2c6f7b0a864c3b", + "components/ts_webui/web/images/README.md": "f4429665c315cdabc2a935caf0f1423632dd7cbff84f34914965969217102237", + "components/ts_webui/web/images/tslogo-48.png": "41f959e327dca63386a2f254b8a245a6fa151904a06eae93ae6c449277467f70", + "components/ts_webui/web/images/tslogo-256.png": "55dc7df59429c23fdc531baba002b7b23f5a4f2be0f29b2ecc5098f3df059da7", + "components/ts_webui/web/images/tslogo-64.png": "a0809405c5632eb4bf1f1b4783175c2b92b25fc522f5b0682a35d3cfa1c58752", + "components/ts_webui/web/images/favicon.icns": "bdc873fa7bff5e1888d80273f99f22d97d3719d4b17419e68e64eafd85c2b039", + "components/ts_webui/web/images/tslogo-original.png": "9fb0ee8532c2d572d8b235f7586d225f00609cf8defb98b59cf55ae749e83ed1", + "components/ts_webui/web/js/terminal.js": "048ca0d64b9ee52b0c2b4f3f3f7e270a2bbd35fc729dbd513cc7b11dfb26bbcf", + "components/ts_webui/web/js/router.js": "1e73ca3bf272a54aea8c516809e09e10f257b620bf66311bbbe358693fe377d5", + "components/ts_webui/web/js/dragSort.js": "7c5b9159cb8bb88b35222424db6d8bd822d3960899d5c090c17955700d6590af", + "components/ts_webui/web/js/api.js": "6fb266abb3780a0d402d86ad95a3644b8e1f488136ad44dc18ddd83caaa8dab4", + "components/ts_webui/web/js/i18n.js": "2eed1c54b4ef89bc2e4221a3fd900e88bd8d7a11064a04d97dcc3decfdeedbd8", + "components/ts_webui/web/js/app.js": "ad63a38112eab45af87da091f3536156614db526bb85f2c83bafa7867439230b", + "components/ts_webui/web/fonts/remixicon.woff2": "e92dc38bfb1d15dbb9d9ca9e645754f68e7c5b224e33c45a17048bd0cf2407a6", + "components/ts_webui/web/fonts/remixicon.css": "b2218eec4e02513f0feef46f74f13c852152f54eafd83d1274057e3895f0ea1c", + "components/ts_webui/web/js/lang/en-US.js": "70e02d67c772b659e5233356938c8344f1caf740ece2f6c3bbdc1c0a1e3c6f72", + "components/ts_webui/web/js/lang/zh-CN.js": "32ee2006259183f7ef03a98532e39a2a75b39c9ed9ab9680fa6279e90d9ea0af", + "components/ts_core/ts_event/CMakeLists.txt": "c7f2d8ef1c3ac4e5bbfda512be49c5ade6acebf651ae8913e36e3f7e4ddd7506", + "components/ts_core/ts_event/Kconfig": "b1cf0bc9fa8ad38744b11d594a6f3aeb077a8ab88950c9695058e95aaea18929", + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_core/ts_service/CMakeLists.txt": "ec3f90c75a8342547444c03165f61c9e9d5dfd1441598ede2aa93cf1711fac61", + "components/ts_core/ts_service/Kconfig": "3ab9397356f4485ed636b1af167714b75fc3d219386b8774ffe3bae6cfbd4675", + "components/ts_core/ts_service/include/ts_service.h": "2bbabd7738c2fb19880e45c0df169e3d5f6a226bbe1affdee030a7ddf8b2dd87", + "components/ts_core/ts_service/src/ts_service.c": "326b3ab1d4a61eba8b9bf43af26039fc4562092cbea19709764104278c79ec2b", + "components/ts_net/CMakeLists.txt": "d6aaac5a04b06bd536336820df0d5eb8c87e27b3087e5df41e640508314b163c", + "components/ts_net/Kconfig": "ddc14968f72310808d23b849248c7cb49411ed43e0f3c268060fb60da2f26e06", + "components/ts_net/include/ts_net_manager.h": "6ad22613972f51af05eb6d468c04763808d92c1d6a6b0a7225911b24f9c0d9a5", + "components/ts_net/include/ts_nat.h": "1721b9c499ca0da09eb402d7db9211604a7a3414b6e2e7cf88169f872365a229", + "components/ts_net/include/ts_net.h": "2ddcd9233f0f5f63a83fdc6f3d09de3118b5b1cced5d9b009b3126c3b872a98b", + "components/ts_net/include/ts_eth.h": "9f8952c77ade85741afb38aa48f3fb689a94164a2c598eb6c7df9344948cf8ce", + "components/ts_net/include/ts_https_server.h": "f4c25017722b69f2f1bae48df34aa595f15d186ad3ec652b7be9d034e184bc79", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/include/ts_dhcp_server.h": "64e5e854f9b8fd7182f92dfafe594f3d8f1288ddecbbbec2c89b3aabee950c51", + "components/ts_net/include/ts_wifi.h": "25614f917387174bbbb7618010885353008e4488262303b314b87b78ae9f0905", + "components/ts_net/include/ts_time_sync.h": "e3ebf9da5b0c7b30a50a67fe07547e2c7fefd588474552579f4a2bc15ace8ca4", + "components/ts_net/src/ts_dhcp_server.c": "800f32ac5097d4d73807496713a59488adfc417a1ea3be627a097cb4c9da0279", + "components/ts_net/src/ts_wifi.c": "54fdffed9cde1145b5dccc5e9419a72c94f83fbc395b225e76098be09b01ba3d", + "components/ts_net/src/ts_time_sync.c": "d83f4591d1c45de7a89af7126c9921301a06ce2a6cb3890c5d302d491811db56", + "components/ts_net/src/ts_net.c": "2f363e1c6cad3437449c742f42db70240cc34105942cfd2c2f3a854b226b8f92", + "components/ts_net/src/ts_net_manager.c": "4184c6e23f68b160a511fd8c44baa8133c04596fc00fcec459389ec61c14789f", + "components/ts_net/src/ts_nat.c": "e5accbee0cc4b7d0feccecc080b23726af94418f5f2c9645df785eb142a1eb24", + "components/ts_net/src/ts_https_server.c": "50e9e0498aa7265739b99d9131eef726149fac255d20f152190d289df16b8ec9", + "components/ts_net/src/ts_eth.c": "d2350045f8abe2d3bc1c046a51c5c0016b601f69bfe99ff2bfcdec8cf26e47fe", + "components/ts_net/src/ts_http_server.c": "0c8449fb396246074ef9deb404b2d5f98610f4f22f3c1ce70bf2774711dbb6ad", + "tests/ws_subscriptions/test_init.c": "4f7995f2e8c39a6247585e2436475d6ec6473c40479c910a54fa0cd3bf7e3f7a", + "tests/ws_subscriptions/run_reviewer.sh": "9b3ec0cae5ef734f5e9fb47acc630cd7eb36e6701bf716308c885a6162247fed", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/test_manager.c": "0cb62636a0f35b57ab997629d1e2c7d7fe349029cc317379db2d4b688924e8b8", + "tests/ws_subscriptions/test_reviewer.c": "14ef95d866c0b9f38ff2c2350fe37d86e584c6ebc4dc9437ba52feb67241da19", + "tests/ws_subscriptions/test_reviewer_service.c": "3fa82db0882b90d69450ddcd7a50e5904ae60e2cab8e62ea11656ac4c21e2890", + "tests/ws_subscriptions/README.md": "e09376ae55908d07e523740c2ce8626de585c5ccb6c9f67290927bae4cf75857", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/run_reviewer_baseline.sh": "6ea73543f64c6de65f59480300cf2d73ece85b798a7a430df5b55f2adae1bb96", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_reviewer_core.c": "7669567ad82171ae32102779e4fc98c4b88871f9e9f761600a21623378882ef2", + "tests/ws_subscriptions/test_reviewer_http.c": "2b9696ac9dd86be96db383392d3bcf61f81a5ab2e881933d767aad8f91d30c00", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "81819518855ce83e8001669d262a7348a6da2250f620baad78a070370543f606", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "main/ts_core_init.c": "ad9b89b44eef49a72117197da3e2d44a0a9ba73cbf5d1a4c7c6a7e123ea41e1f" + } +} diff --git a/docs/repair/ws-f1-f2/before.txt b/docs/repair/ws-f1-f2/before.txt new file mode 100644 index 0000000..1b6c5eb --- /dev/null +++ b/docs/repair/ws-f1-f2/before.txt @@ -0,0 +1,4 @@ +Frozen production snapshot hashes verified +F1 assertion: accepted SSH output enqueue failure reaches session and error frame: FAIL (stream still normal / no error frame) +F2 assertion: protection transition survives ordinary log pool saturation: FAIL (no protection frame) +CONFIRMED: both failures are behavioral assertions, not compilation or cleanup failures diff --git a/docs/repair/ws-f1-f2/browser.txt b/docs/repair/ws-f1-f2/browser.txt new file mode 100644 index 0000000..992b6f8 --- /dev/null +++ b/docs/repair/ws-f1-f2/browser.txt @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (863.624416ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (264.000125ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (336.359375ms) +✔ en-US: initial language failure blocks controls and retry recovers (332.763167ms) +✔ delayed language package and rapid switches keep the latest requested language (269.526917ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (394.635958ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (295.476084ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (350.459167ms) +✔ initial delayed language keeps controls inert until the real package arrives (269.896583ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (360.269667ms) +✔ terminal can initialize after failed resource load using newly served resources (385.252583ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (795.63775ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (192.548625ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (173.148458ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (254.46475ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (262.009458ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (276.228375ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (178.136541ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (199.093458ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (195.149125ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (204.450667ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (214.213334ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (181.424667ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (267.542208ms) +✔ R3: late validation cannot revive an old apply entry en-US (279.31025ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (262.818583ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (240.923042ms) +✔ R6: fixed upload destination and separate refresh failure en-US (234.020459ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (240.173ms) +✔ R2: authenticated startup initializes once (284.374791ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (230.044792ms) +✔ R4/R5: newest result wins over late success and late failure (234.647208ms) +✔ R3: overlapping writes to one path cannot claim current verified content (220.72775ms) +✔ R2: disposed page only removes its dashboard callback (254.038292ms) +✔ R2: stale finally cannot unlock the new page read (218.574583ms) +✔ R1: delayed sign-out does not clear a newer sign-in (237.443625ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (309.375958ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (356.428833ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 7352.504834 diff --git a/docs/repair/ws-f1-f2/build.txt b/docs/repair/ws-f1-f2/build.txt new file mode 100644 index 0000000..7540647 --- /dev/null +++ b/docs/repair/ws-f1-f2/build.txt @@ -0,0 +1,33 @@ +Executing action: all (aliases: build) +Running ninja in directory /private/tmp/tianshan-ws-build/build +Executing "ninja all"... +[1/13] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-ws-build/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ws-build/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[2/13] No install step for 'bootloader' +[3/13] cd /tmp/tianshan-ws-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ws-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ws-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[4/13] Completed 'bootloader' +[5/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_api.c.obj +[6/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[7/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_transport.c.obj +[8/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[9/13] Linking C static library esp-idf/ts_webui/libts_webui.a +[10/13] Generating esp-idf/esp_system/ld/sections.ld +[11/13] Linking CXX executable TianShanOS.elf +[12/13] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-ws-build/build/TianShanOS.bin +[13/13] cd /tmp/tianshan-ws-build/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ws-build/build/partition_table/partition-table.bin /tmp/tianshan-ws-build/build/TianShanOS.bin +TianShanOS.bin binary size 0x213f70 bytes. Smallest app partition is 0x300000 bytes. 0xec090 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-ws-build/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-ws-build/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-ws-build/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-ws-build/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-ws-build/build/www.bin +or from the "/private/tmp/tianshan-ws-build/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ws-f1-f2/certificate.txt b/docs/repair/ws-f1-f2/certificate.txt new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ws-f1-f2/certificate.txt @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ws-f1-f2/changes.patch b/docs/repair/ws-f1-f2/changes.patch new file mode 100644 index 0000000..346b5ed --- /dev/null +++ b/docs/repair/ws-f1-f2/changes.patch @@ -0,0 +1,1012 @@ +diff --git a/components/ts_webui/include/ts_ws_transport.h b/components/ts_webui/include/ts_ws_transport.h +index f92fc32..bbd37ee 100644 +--- a/components/ts_webui/include/ts_ws_transport.h ++++ b/components/ts_webui/include/ts_ws_transport.h +@@ -7,8 +7,14 @@ + #define TS_WS_TOPIC_TX_SLOTS 32 + #define TS_WS_TX_SLOTS (TS_WS_TOPIC_TX_SLOTS + TS_WS_CONNECTIONS) + #define TS_WS_MESSAGE_SLOTS 8 +-#define TS_WS_ALL_MESSAGE_SLOTS (TS_WS_MESSAGE_SLOTS + 2) +-#define TS_WS_ALL_TX_SLOTS (TS_WS_TX_SLOTS + 2 * TS_WS_CONNECTIONS) ++#define TS_WS_POWER_TRANSITIONS 4 ++#define TS_WS_POWER_SLOTS (TS_WS_POWER_TRANSITIONS + 1) ++#define TS_WS_POWER_BYTES 1024 ++#define TS_WS_POWER_BUDGET (TS_WS_POWER_SLOTS * TS_WS_POWER_BYTES) ++#define TS_WS_QUEUE_RETRIES 300 /* 100 ms backoff, bounded SDK admission retries */ ++#define TS_WS_ALL_MESSAGE_SLOTS (TS_WS_MESSAGE_SLOTS + 2 + TS_WS_POWER_SLOTS) ++#define TS_WS_RESULT_TX_END (TS_WS_TX_SLOTS + 2 * TS_WS_CONNECTIONS) ++#define TS_WS_ALL_TX_SLOTS (TS_WS_RESULT_TX_END + TS_WS_POWER_SLOTS * TS_WS_CONNECTIONS) + #define TS_WS_FRAME_BYTES 32768 + #define TS_WS_LEGACY_BYTES (512 * 1024) + #define TS_WS_TOTAL_BYTES (1024 * 1024) +@@ -39,6 +45,9 @@ unsigned ts_ws_transport_capacity(void); + ts_ws_message_t *ts_ws_message_json(const char *topic, const cJSON *data, int64_t timestamp); + ts_ws_message_t *ts_ws_message_text(const char *text, size_t len); + void ts_ws_message_release(ts_ws_message_t *message); ++/* ESP_OK means local acceptance. Each accepted target settles once via done, ++ * including later queue failure, stale/canceled target and socket failure. ++ * A synchronous rejection never calls done. Message origin selects its pool. */ + esp_err_t ts_ws_transport_submit(ts_ws_peer_t peer, ts_ws_message_t *message, + uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done); + /* Compatibility bridge for existing global/stream senders; never coalesces. */ +@@ -69,6 +78,7 @@ static inline bool ts_ws_json_reference(cJSON *object, const char *key, const cJ + + typedef struct { + uint64_t queued, attempts, success, failed, stale, rejected; ++ uint64_t settled, power_accepted, power_rejected, power_settled, power_failed; + uint32_t bytes, bytes_high, jobs, jobs_high; + int64_t max_send_us; + } ts_ws_transport_stats_t; +@@ -107,3 +117,11 @@ esp_err_t ts_ws_result_reserve(size_t bytes, ts_ws_reservation_t *r); + esp_err_t ts_ws_result_broadcast(ts_ws_reservation_t *r, const char *text); + + uint32_t ts_ws_transport_retry_ms(void); ++ ++/* Fixed power payloads and exclusive descriptors/byte budget. Tick traffic has ++ * its own slot; neither ticks nor ordinary logs consume transition capacity. ++ * Snapshot recipients at admission; no coalescing or re-broadcast on retry. */ ++esp_err_t ts_ws_power_reserve(bool tick, ts_ws_reservation_t *r); ++esp_err_t ts_ws_power_publish(ts_ws_reservation_t *r, const char *text); ++ ++esp_err_t ts_ws_result_publish(ts_ws_reservation_t *r,const ts_ws_peer_t *peers,unsigned count); +diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c +index 9d10d30..6d0f56c 100644 +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #define TAG "webui_ws" + +@@ -84,6 +85,17 @@ enum { SSH_IDLE, SSH_STARTING, SSH_READY, SSH_TERMINAL }; + static atomic_uint s_ssh_state, s_ssh_generation, s_ssh_result_pending; + static ts_ws_reservation_t s_ssh_terminal; + static ts_ws_reservation_t s_exec_terminal; ++/* One producer per stream. Pending includes each accepted destination, including ++ * publication callbacks that can run before submit returns. Terminal buffers ++ * are not published/released until all earlier output has settled. */ ++static atomic_uint s_ssh_output_pending, s_exec_output_pending; ++static atomic_bool s_ssh_output_failed, s_exec_output_failed; ++static atomic_bool s_ssh_terminal_ready, s_exec_terminal_ready, s_exec_result_active, s_exec_terminal_claimed; ++static ts_ws_peer_t s_exec_result_peers[TS_WS_CONNECTIONS]; ++static unsigned s_exec_result_count; ++static void ssh_terminal_flush(void); ++static void ssh_exec_terminal_flush(void); ++static void ssh_exec_terminal_publish(const char *json,uint32_t session_id); + + /* SSH Exec 流式执行状态 */ + static ts_ssh_session_t s_exec_session = NULL; +@@ -146,36 +158,36 @@ static void power_policy_event_handler(const ts_event_t *event, void *user_data) + + ts_power_policy_status_t *status = (ts_power_policy_status_t *)event->data; + +- // 构造事件消息 +- cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", "power_event"); +- cJSON_AddStringToObject(msg, "state", power_state_to_string(status->state)); +- cJSON_AddNumberToObject(msg, "voltage", status->current_voltage); +- cJSON_AddNumberToObject(msg, "countdown", status->countdown_remaining_sec); +- cJSON_AddNumberToObject(msg, "protection_count", status->protection_count); +- +- // 根据事件 ID 添加具体事件类型(使用 ts_power_policy_event_t 枚举值) +- const char *event_name = "unknown"; +- switch (event->id) { +- case TS_POWER_POLICY_EVENT_STATE_CHANGED: event_name = "state_changed"; break; +- case TS_POWER_POLICY_EVENT_LOW_VOLTAGE: event_name = "low_voltage"; break; +- case TS_POWER_POLICY_EVENT_COUNTDOWN_TICK: event_name = "countdown_tick"; break; +- case TS_POWER_POLICY_EVENT_SHUTDOWN_START: event_name = "shutdown_start"; break; +- case TS_POWER_POLICY_EVENT_PROTECTED: event_name = "protected"; break; +- case TS_POWER_POLICY_EVENT_RECOVERY_START: event_name = "recovery_start"; break; +- case TS_POWER_POLICY_EVENT_RECOVERY_COMPLETE: event_name = "recovery_complete"; break; +- case TS_POWER_POLICY_EVENT_DEBUG_TICK: event_name = "debug_tick"; break; +- } +- cJSON_AddStringToObject(msg, "event", event_name); +- +- char *json = cJSON_PrintUnformatted(msg); +- cJSON_Delete(msg); +- +- if (json) { +- // 广播给所有连接的客户端 +- ts_webui_broadcast(json); +- free(json); +- } ++ bool tick=event->id==TS_POWER_POLICY_EVENT_COUNTDOWN_TICK || event->id==TS_POWER_POLICY_EVENT_DEBUG_TICK; ++ ts_ws_reservation_t reservation; ++ esp_err_t ret=ts_ws_power_reserve(tick,&reservation); ++ if(ret!=ESP_OK) { ++ TS_LOGW(TAG,"Power notification admission failed: event=%ld result=%d",(long)event->id,ret); ++ return; /* bounded overload; never wait on protection's event callback */ ++ } ++ if(!reservation.message)return; ++ const char *event_name="unknown"; ++ switch(event->id) { ++ case TS_POWER_POLICY_EVENT_STATE_CHANGED:event_name="state_changed";break; ++ case TS_POWER_POLICY_EVENT_LOW_VOLTAGE:event_name="low_voltage";break; ++ case TS_POWER_POLICY_EVENT_COUNTDOWN_TICK:event_name="countdown_tick";break; ++ case TS_POWER_POLICY_EVENT_SHUTDOWN_START:event_name="shutdown_start";break; ++ case TS_POWER_POLICY_EVENT_PROTECTED:event_name="protected";break; ++ case TS_POWER_POLICY_EVENT_RECOVERY_START:event_name="recovery_start";break; ++ case TS_POWER_POLICY_EVENT_RECOVERY_COMPLETE:event_name="recovery_complete";break; ++ case TS_POWER_POLICY_EVENT_DEBUG_TICK:event_name="debug_tick";break; ++ } ++ /* Fixed schema, numeric values and constant strings; no heap JSON needed. ++ * Preserve cJSON's non-finite-number encoding as null. */ ++ char voltage[32],json[512]; ++ if(isfinite(status->current_voltage))snprintf(voltage,sizeof(voltage),"%.17g",(double)status->current_voltage); ++ else strcpy(voltage,"null"); ++ int n=snprintf(json,sizeof(json),"{\"type\":\"power_event\",\"state\":\"%s\",\"voltage\":%s,\"countdown\":%lu,\"protection_count\":%lu,\"event\":\"%s\"}", ++ power_state_to_string(status->state),voltage,(unsigned long)status->countdown_remaining_sec,(unsigned long)status->protection_count,event_name); ++ ret=n<0 || n>=(int)sizeof(json)?ESP_ERR_INVALID_SIZE:ts_ws_power_publish(&reservation,json); ++ ts_ws_reservation_release(&reservation); ++ if(ret!=ESP_OK)TS_LOGW(TAG,"Power notification submission failed: event=%ld result=%d",(long)event->id,ret); ++ + } + + /*===========================================================================*/ +@@ -212,10 +224,34 @@ static void ssh_request_error(httpd_req_t *req, const char *message) + free(json); + } + ++static void ssh_output_done(uint64_t generation,uint64_t delivery,esp_err_t result) ++{ ++ (void)delivery; /* transport already validates full peer identity */ ++ if(generation!=s_ssh_generation)return; ++ if(result!=ESP_OK){s_ssh_output_failed=true;s_ssh_running=false;} ++ atomic_fetch_sub(&s_ssh_output_pending,1); ++ if(result!=ESP_OK)ssh_send_status("error","SSH output delivery incomplete; remote command result is not confirmed"); ++ ssh_terminal_flush(); ++} ++static void ssh_terminal_flush(void) ++{ ++ if(s_ssh_output_pending)return; ++ bool ready=true; ++ if(!atomic_compare_exchange_strong(&s_ssh_terminal_ready,&ready,false))return; ++ unsigned generation=s_ssh_generation; ++ if(s_ssh_output_failed)ts_ws_reserved_text(&s_ssh_terminal, ++ "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}"); ++ ts_ws_reservation_t terminal=s_ssh_terminal; ++ s_ssh_terminal=(ts_ws_reservation_t){0}; ++ esp_err_t ret=ts_ws_reserved_submit(&terminal,0,generation,SSH_TERMINAL,ssh_status_valid,ssh_terminal_done); ++ if(ret!=ESP_OK)ssh_terminal_done(generation,SSH_TERMINAL,ret); ++ ts_ws_reservation_release(&terminal); ++} ++ + /* 发送 SSH 输出到 WebSocket 客户端 */ + static void ssh_send_output(const char *data, size_t len) + { +- if(s_ssh_client_fd<0 || !s_server || !data || !len)return; ++ if(s_ssh_client_fd<0 || !s_server || !data || !len || s_ssh_state!=SSH_READY)return; + esp_err_t ret=ESP_ERR_NO_MEM; + char *buf=heap_caps_malloc(len+1,MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + if(!buf)buf=malloc(len+1); +@@ -230,11 +266,17 @@ static void ssh_send_output(const char *data, size_t len) + free(buf);cJSON_Delete(msg); + if(json) { + ts_ws_message_t *m=ts_ws_message_text(json,strlen(json)); +- if(m)ret=ts_ws_transport_submit(s_ssh_peer,m,s_ssh_generation,0,ssh_generation_valid,NULL); ++ if(m) { ++ atomic_fetch_add(&s_ssh_output_pending,1); ++ ret=ts_ws_transport_submit(s_ssh_peer,m,s_ssh_generation,s_ssh_peer.connection,ssh_generation_valid,ssh_output_done); ++ /* Rejection was never accepted and has no completion callback. */ ++ if(ret!=ESP_OK)ssh_output_done(s_ssh_generation,s_ssh_peer.connection,ret); ++ } + ts_ws_message_release(m); + } + free(json); + if(ret!=ESP_OK) { ++ s_ssh_output_failed=true; + TS_LOGW(TAG,"SSH output rejected: %s",esp_err_to_name(ret)); + ssh_send_status("error","SSH output delivery failed"); + s_ssh_running=false; +@@ -265,12 +307,9 @@ static esp_err_t ssh_send_status(const char *status, const char *message) + TS_LOGW(TAG,"SSH terminal encoding failed: %s",esp_err_to_name(ret)); + ret=ts_ws_reserved_text(&s_ssh_terminal,fallback); + } +- if(ret==ESP_OK) { +- s_ssh_result_pending=generation; +- ret=ts_ws_reserved_submit(&s_ssh_terminal,0,generation,state,ssh_status_valid,ssh_terminal_done); +- if(ret!=ESP_OK)ssh_terminal_done(generation,state,ret); +- } +- ts_ws_reservation_release(&s_ssh_terminal); ++ s_ssh_result_pending=generation; ++ if(ret==ESP_OK){s_ssh_terminal_ready=true;ssh_terminal_flush();} ++ else {ssh_terminal_done(generation,state,ret);ts_ws_reservation_release(&s_ssh_terminal);} + } else if(json && ssh_status_valid(generation,state)) { + httpd_ws_frame_t frame={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)json,.len=strlen(json)}; + if(ts_ws_transport_in_context()) ret=ts_ws_transport_send(s_ssh_peer.server,s_ssh_peer.fd,&frame); +@@ -376,7 +415,7 @@ static void ssh_cleanup(void) + } + if(s_ssh_state==SSH_READY) ssh_send_status("closed","SSH session closed"); + s_ssh_client_fd = -1; +- ts_ws_reservation_release(&s_ssh_terminal); ++ if(!s_ssh_result_pending && !s_ssh_output_pending)ts_ws_reservation_release(&s_ssh_terminal); + + TS_LOGD(TAG, "SSH session cleaned up"); + } +@@ -384,7 +423,7 @@ static void ssh_cleanup(void) + /* 处理 SSH Shell 连接请求 */ + static void handle_ssh_connect(httpd_req_t *req, cJSON *params) + { +- if (s_ssh_result_pending) { ++ if (s_ssh_result_pending || s_ssh_output_pending) { + ssh_request_error(req,"Previous SSH result is still pending"); + return; + } +@@ -422,6 +461,8 @@ static void handle_ssh_connect(httpd_req_t *req, cJSON *params) + ssh_request_error(req,"SSH result delivery capacity unavailable"); + return; + } ++ s_ssh_output_failed=false; ++ s_ssh_terminal_ready=false; + s_ssh_generation++; + s_ssh_state=SSH_STARTING; + // 设置 SSH 客户端 fd +@@ -1255,6 +1296,7 @@ esp_err_t ts_webui_ws_stop(httpd_handle_t server) + if (ret != ESP_OK) return ret; + ret = ts_ws_subscriptions_drain(); + if (ret != ESP_OK) return ret; ++ if(s_exec_result_active || s_ssh_result_pending || s_ssh_output_pending)return ESP_ERR_INVALID_STATE; + ret = ts_ws_transport_stop(server, 6000); + if (ret != ESP_OK) return ret; + return ts_ws_subscriptions_deinit(); +@@ -1513,6 +1555,31 @@ static bool simple_pattern_match(const char *text, const char *pattern, char **e + } + } + ++static void ssh_exec_output_done(uint64_t session,uint64_t connection,esp_err_t result) ++{ ++ (void)connection; ++ if(session!=s_exec_session_id)return; ++ if(result!=ESP_OK)s_exec_output_failed=true; ++ atomic_fetch_sub(&s_exec_output_pending,1); ++ if(result!=ESP_OK)ssh_exec_terminal_publish(NULL,(uint32_t)session); ++ ssh_exec_terminal_flush(); ++} ++static void ssh_exec_stream_publish(const char *json,uint32_t session) ++{ ++ if(session!=s_exec_session_id || s_exec_output_failed)return; ++ ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); ++ if(!n)return; ++ ts_ws_message_t *m=json?ts_ws_message_text(json,strlen(json)):NULL; ++ if(!m){s_exec_output_failed=true;ssh_exec_terminal_publish(NULL,session);return;} ++ atomic_fetch_add(&s_exec_output_pending,n); /* register the whole fanout before any early callback */ ++ for(unsigned i=0;ioutput_buffer) { + const char *output = s_exec_params->output_buffer; +@@ -1641,10 +1696,8 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + + char *match_json = cJSON_PrintUnformatted(match_msg); + cJSON_Delete(match_msg); +- if (match_json) { +- ts_webui_broadcast(match_json); +- free(match_json); +- } ++ ssh_exec_stream_publish(match_json,session_id); ++ free(match_json); + + /* ========== 根据命令类型决定变量更新时机 ========== */ + /* +@@ -1734,14 +1787,34 @@ static void ssh_exec_timeout_callback(TimerHandle_t xTimer) + + /* Every accepted streamed command owns one result reservation. Ordinary output + * cannot consume it. Oversize/encoding failure is reported, never as success. */ ++static void ssh_exec_terminal_flush(void) ++{ ++ if(s_exec_output_pending)return; ++ bool ready=true; ++ if(!atomic_compare_exchange_strong(&s_exec_terminal_ready,&ready,false))return; ++ if(s_exec_output_failed) { ++ char fallback[224]; ++ snprintf(fallback,sizeof(fallback),"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"SSH output delivery incomplete; remote command result is not confirmed\"}",(unsigned long)s_exec_session_id); ++ ts_ws_reserved_text(&s_exec_terminal,fallback); ++ } ++ /* Completion owns the original recipient snapshot; never retarget on retry. */ ++ esp_err_t ret=ts_ws_result_publish(&s_exec_terminal,s_exec_result_peers,s_exec_result_count); ++ if(ret!=ESP_OK)TS_LOGW(TAG,"SSH terminal result rejected: %s",esp_err_to_name(ret)); ++ ts_ws_reservation_release(&s_exec_terminal); ++ s_exec_result_active=false; ++} + static void ssh_exec_terminal_publish(const char *json,uint32_t session_id) + { ++ bool claimed=false; ++ if(!atomic_compare_exchange_strong(&s_exec_terminal_claimed,&claimed,true))return; + char fallback[192]; + snprintf(fallback,sizeof(fallback),"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"SSH result delivery failed; result is unknown\"}",(unsigned long)session_id); +- esp_err_t ret=ts_ws_result_broadcast(&s_exec_terminal,json?json:fallback); +- if(ret==ESP_ERR_INVALID_SIZE)ret=ts_ws_result_broadcast(&s_exec_terminal,fallback); +- if(ret!=ESP_OK)TS_LOGW(TAG,"SSH terminal result rejected: %s",esp_err_to_name(ret)); +- ts_ws_reservation_release(&s_exec_terminal); ++ esp_err_t ret=ts_ws_reserved_text(&s_exec_terminal,json?json:fallback); ++ if(ret!=ESP_OK)ret=ts_ws_reserved_text(&s_exec_terminal,fallback); ++ if(ret!=ESP_OK){TS_LOGW(TAG,"SSH terminal encoding failed: %s",esp_err_to_name(ret));ts_ws_reservation_release(&s_exec_terminal);s_exec_result_active=false;return;} ++ s_exec_result_count=ts_ws_peer_snapshot(s_exec_result_peers,TS_WS_CONNECTIONS); ++ s_exec_terminal_ready=true; ++ ssh_exec_terminal_flush(); + } + + /* SSH Exec 任务 */ +@@ -1830,7 +1903,7 @@ static void ssh_exec_task(void *arg) + } + char *json = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); +- if (json) { ts_webui_broadcast(json); free(json); } ++ ssh_exec_stream_publish(json,session_id); free(json); + } + + /* 判断是否需要启动超时定时器 */ +@@ -2218,11 +2291,12 @@ esp_err_t ts_webui_ssh_exec_start(const char *host, uint16_t port, + { + unsigned creators = atomic_fetch_add(&s_exec_creators, 1); + esp_err_t ret=ESP_ERR_INVALID_STATE; +- if(!creators && !s_ws_stopping && !s_exec_running) { ++ if(!creators && !s_ws_stopping && !s_exec_running && !s_exec_result_active) { + ret=ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal); ++ if(ret==ESP_OK){s_exec_result_active=true;s_exec_output_failed=false;s_exec_terminal_ready=false;s_exec_terminal_claimed=false;} + if(ret==ESP_OK) { + ret=ts_webui_ssh_exec_start_impl(host, port, user, keyid, password, command, session_id); +- if(ret!=ESP_OK)ts_ws_reservation_release(&s_exec_terminal); ++ if(ret!=ESP_OK){ts_ws_reservation_release(&s_exec_terminal);s_exec_result_active=false;} + } + } + atomic_fetch_sub(&s_exec_creators, 1); +@@ -2441,11 +2515,12 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, + { + unsigned creators = atomic_fetch_add(&s_exec_creators, 1); + esp_err_t ret=ESP_ERR_INVALID_STATE; +- if(!creators && !s_ws_stopping && !s_exec_running) { ++ if(!creators && !s_ws_stopping && !s_exec_running && !s_exec_result_active) { + ret=ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal); ++ if(ret==ESP_OK){s_exec_result_active=true;s_exec_output_failed=false;s_exec_terminal_ready=false;s_exec_terminal_claimed=false;} + if(ret==ESP_OK) { + ret=ts_webui_ssh_exec_start_ex_impl(host, port, user, keyid, password, command, options, session_id); +- if(ret!=ESP_OK)ts_ws_reservation_release(&s_exec_terminal); ++ if(ret!=ESP_OK){ts_ws_reservation_release(&s_exec_terminal);s_exec_result_active=false;} + } + } + atomic_fetch_sub(&s_exec_creators, 1); +diff --git a/components/ts_webui/src/ts_ws_transport.c b/components/ts_webui/src/ts_ws_transport.c +index f08d9da..81c4ba3 100644 +--- a/components/ts_webui/src/ts_ws_transport.c ++++ b/components/ts_webui/src/ts_ws_transport.c +@@ -1,5 +1,6 @@ + #include "ts_ws_transport.h" + #include "esp_timer.h" ++#include "esp_log.h" + #include "freertos/FreeRTOS.h" + #include "freertos/task.h" + #include +@@ -22,12 +23,15 @@ static struct { + static ts_ws_peer_t s_peers[TS_WS_CONNECTIONS]; + static int s_log_levels[TS_WS_CONNECTIONS]; + static uint64_t s_log_revisions[TS_WS_CONNECTIONS]; +-struct ts_ws_message { unsigned refs; char *text; size_t len, capacity; }; ++typedef enum {MSG_ORDINARY, MSG_TOPIC, MSG_RESULT, MSG_POWER, MSG_POWER_TICK} message_kind_t; ++struct ts_ws_message { unsigned refs; char *text; size_t len, capacity; message_kind_t kind; }; ++static char s_power_payloads[TS_WS_POWER_SLOTS][TS_WS_POWER_BYTES]; ++static unsigned s_power_bytes; + static ts_ws_transport_stats_t s_tx_stats; + static ts_ws_message_t s_messages[TS_WS_ALL_MESSAGE_SLOTS]; + typedef enum {TX_FREE, TX_RESERVED, TX_PREPARED, TX_QUEUED, TX_EXECUTING, TX_DONE, TX_CANCELED} tx_state_t; + typedef struct { +- unsigned refs; ++ unsigned refs, retries; + tx_state_t state; + uint64_t order; + ts_ws_peer_t peer; +@@ -128,21 +132,25 @@ esp_err_t ts_ws_peer_open(httpd_req_t *req, ts_ws_peer_t *peer) + req->free_ctx = session_free; /* RST, LRU and httpd_stop also release this. */ + return ESP_OK; + } +-static ts_ws_message_t *message_alloc(size_t capacity, unsigned kind) ++static ts_ws_message_t *message_alloc(size_t capacity, message_kind_t kind) + { ++ if(kind>=MSG_POWER && capacity>TS_WS_POWER_BYTES)return NULL; + ts_ws_message_t *m = NULL; + portENTER_CRITICAL(&s_lock); +- unsigned begin=kind==2 ? TS_WS_MESSAGE_SLOTS : kind==1 ? 0 : TS_WS_MESSAGE_SLOTS-2; +- unsigned end=kind==2 ? TS_WS_ALL_MESSAGE_SLOTS : kind==1 ? TS_WS_MESSAGE_SLOTS-2 : TS_WS_MESSAGE_SLOTS; +- for (unsigned i=begin; capacity <= TS_WS_TOTAL_BYTES-s_tx_stats.bytes && irefs = 1; m->capacity = capacity; ++ unsigned begin=kind>=MSG_POWER ? TS_WS_MESSAGE_SLOTS+2+(kind==MSG_POWER_TICK?TS_WS_POWER_TRANSITIONS:0) : kind==MSG_RESULT ? TS_WS_MESSAGE_SLOTS : kind==MSG_TOPIC ? 0 : TS_WS_MESSAGE_SLOTS-2; ++ unsigned end=kind==MSG_POWER_TICK ? TS_WS_ALL_MESSAGE_SLOTS : kind==MSG_POWER ? TS_WS_ALL_MESSAGE_SLOTS-1 : kind==MSG_RESULT ? TS_WS_MESSAGE_SLOTS+2 : kind==MSG_TOPIC ? TS_WS_MESSAGE_SLOTS-2 : TS_WS_MESSAGE_SLOTS; ++ size_t used=kind>=MSG_POWER ? s_power_bytes : s_tx_stats.bytes-s_power_bytes; ++ size_t limit=kind>=MSG_POWER ? TS_WS_POWER_BUDGET : TS_WS_TOTAL_BYTES-TS_WS_POWER_BUDGET; ++ for (unsigned i=begin; capacity <= limit-used && irefs = 1; m->capacity = capacity; m->kind=kind; ++ if(kind>=MSG_POWER)s_power_bytes+=capacity; + s_tx_stats.bytes += capacity; + if(s_tx_stats.bytes > s_tx_stats.bytes_high) s_tx_stats.bytes_high=s_tx_stats.bytes; + break; + } + portEXIT_CRITICAL(&s_lock); + if (m) { +- m->text = malloc(capacity); ++ m->text = kind>=MSG_POWER ? s_power_payloads[m-s_messages-TS_WS_MESSAGE_SLOTS-2] : malloc(capacity); + if (!m->text) { + portENTER_CRITICAL(&s_lock);s_tx_stats.rejected++;portEXIT_CRITICAL(&s_lock); + ts_ws_message_release(m);return NULL; +@@ -166,8 +174,9 @@ void ts_ws_message_release(ts_ws_message_t *m) + } + portEXIT_CRITICAL(&s_lock); + if (!reclaim) return; +- free(text); ++ if(m->kindkind>=MSG_POWER)s_power_bytes-=m->capacity; + m->text = NULL; + m->len = 0; + s_tx_stats.bytes -= m->capacity; +@@ -220,6 +229,18 @@ static void delivery_release(delivery_t *d) + portEXIT_CRITICAL(&s_lock); + ts_ws_message_release(m); + } ++/* Exactly one settlement for every accepted work reference, including stale ++ * targets and queue rejection. Class is owned by the message, never by done. */ ++static void settle(delivery_t *d, esp_err_t result) ++{ ++ portENTER_CRITICAL(&s_lock); ++ s_tx_stats.settled++; ++ bool power=d->message->kind>=MSG_POWER; ++ if(power){s_tx_stats.power_settled++;if(result!=ESP_OK)s_tx_stats.power_failed++;} ++ portEXIT_CRITICAL(&s_lock); ++ if(d->message->kind>=MSG_RESULT && result!=ESP_OK)ESP_LOGW("ws_tx","Critical notification target failed: class=%d fd=%d result=%d",d->message->kind,d->peer.fd,result); ++ if(d->done)d->done(d->revision,d->delivery,result); ++} + static void deliver(void *arg) + { + delivery_t *d = arg; +@@ -253,7 +274,7 @@ static void deliver(void *arg) + portENTER_CRITICAL(&s_lock); s_tx_stats.stale++; portEXIT_CRITICAL(&s_lock); + } + TS_WS_TEST_POINT("sent"); +- if (d->done) d->done(d->revision, d->delivery, ret); ++ settle(d,ret); + portENTER_CRITICAL(&s_lock); + d->state=TX_DONE; + s_server.work_busy=false; +@@ -268,19 +289,22 @@ static esp_err_t publish_delivery(delivery_t *d) + { + esp_err_t ret=httpd_queue_work(d->peer.server,deliver,d); + portENTER_CRITICAL(&s_lock); +- bool retry=ret!=ESP_OK && d>=&s_deliveries[TS_WS_TX_SLOTS]; ++ bool retry=ret!=ESP_OK && d->message->kind>=MSG_RESULT && ++d->retriesstate=retry?TX_PREPARED:TX_CANCELED; + if(retry)s_server.retry_at=esp_timer_get_time()+100000; + } + portEXIT_CRITICAL(&s_lock); + if(ret!=ESP_OK){ + if(!retry) { +- if(d->done)d->done(d->revision,d->delivery,ret); ++ settle(d,ret); + delivery_release(d); /* failed ordinary work reference */ + } ++ /* A failure callback may enqueue its reserved terminal. Keep the ++ * executor busy until settlement ends to avoid recursive queue failures. */ ++ portENTER_CRITICAL(&s_lock);s_server.work_busy=false;portEXIT_CRITICAL(&s_lock); + ts_ws_subscriptions_wake(); + } + delivery_release(d); /* publication reference, may outlive the callback */ +@@ -315,18 +339,18 @@ static void cancel_ready(bool topics_only) + bool cancel=d->state==TX_PREPARED && (!topics_only || istate=TX_CANCELED;s_tx_stats.stale++;} /* take its existing work reference */ + portEXIT_CRITICAL(&s_lock); +- if(cancel){if(d->done)d->done(d->revision,d->delivery,ESP_ERR_INVALID_STATE);delivery_release(d);} ++ if(cancel){settle(d,ESP_ERR_INVALID_STATE);delivery_release(d);} + } + } + void ts_ws_transport_cancel_topics(void){cancel_ready(true);} + esp_err_t ts_ws_transport_submit(ts_ws_peer_t peer, ts_ws_message_t *message, + uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done) + { +- if(!message)return ESP_ERR_INVALID_ARG; ++ if(!message || message->kind>MSG_TOPIC)return ESP_ERR_INVALID_ARG; + delivery_t *d=NULL; + portENTER_CRITICAL(&s_lock); + if(!s_server.stopping && peer_valid(peer) && s_delivery_order!=UINT64_MAX) +- for(unsigned i=done?0:TS_WS_TOPIC_TX_SLOTS;i<(done?TS_WS_TOPIC_TX_SLOTS:TS_WS_TX_SLOTS);i++)if(!s_deliveries[i].refs){ ++ for(unsigned i=message->kind==MSG_TOPIC?0:TS_WS_TOPIC_TX_SLOTS;i<(message->kind==MSG_TOPIC?TS_WS_TOPIC_TX_SLOTS:TS_WS_TX_SLOTS);i++)if(!s_deliveries[i].refs){ + d=&s_deliveries[i]; + *d=(delivery_t){.refs=2,.state=TX_PREPARED,.order=++s_delivery_order,.peer=peer, + .message=message,.revision=revision,.delivery=delivery,.check=check,.done=done}; +@@ -436,7 +460,7 @@ unsigned ts_ws_message_capacity(void) + { + unsigned n=0; + portENTER_CRITICAL(&s_lock); +- if(s_tx_stats.bytes <= TS_WS_TOTAL_BYTES - TS_WS_FRAME_BYTES) ++ if(s_tx_stats.bytes-s_power_bytes <= TS_WS_TOTAL_BYTES-TS_WS_POWER_BUDGET-TS_WS_FRAME_BYTES) + for(unsigned i=0;iTS_WS_RESERVATION_TARGETS || !bytes || bytes>TS_WS_LEGACY_BYTES) return ESP_ERR_INVALID_ARG; ++ if(!r || (!peers && kind!=MSG_RESULT) || !count || count>TS_WS_RESERVATION_TARGETS || !bytes || bytes>TS_WS_LEGACY_BYTES) return ESP_ERR_INVALID_ARG; + *r=(ts_ws_reservation_t){0}; +- ts_ws_message_t *m=message_alloc(bytes,result?2:1); ++ ts_ws_message_t *m=message_alloc(bytes,kind); + if(!m) return ESP_ERR_NO_MEM; +- unsigned begin=result?TS_WS_TX_SLOTS:0, end=result?TS_WS_ALL_TX_SLOTS:TS_WS_TOPIC_TX_SLOTS; ++ unsigned begin=kind>=MSG_POWER ? TS_WS_RESULT_TX_END+(kind==MSG_POWER_TICK?TS_WS_POWER_TRANSITIONS*TS_WS_CONNECTIONS:0) : kind==MSG_RESULT?TS_WS_TX_SLOTS:0; ++ unsigned end=kind==MSG_POWER_TICK?TS_WS_ALL_TX_SLOTS:kind==MSG_POWER?TS_WS_ALL_TX_SLOTS-TS_WS_CONNECTIONS:kind==MSG_RESULT?TS_WS_RESULT_TX_END:TS_WS_TOPIC_TX_SLOTS; + portENTER_CRITICAL(&s_lock); + bool valid=!s_server.stopping && s_server.handle; + for(unsigned i=0;peers && imessage){ts_ws_message_release(m);return valid?ESP_ERR_NO_MEM:ESP_ERR_INVALID_STATE;} + return ESP_OK; + } ++esp_err_t ts_ws_reserve(const ts_ws_peer_t *peers,unsigned count,bool result,size_t bytes,ts_ws_reservation_t *r) ++{ ++ return reserve_kind(peers,count,result?MSG_RESULT:MSG_TOPIC,bytes,r); ++} + void ts_ws_reservation_release(ts_ws_reservation_t *r) + { + if(!r || !r->message)return; +@@ -573,6 +602,11 @@ esp_err_t ts_ws_result_broadcast(ts_ws_reservation_t *r,const char *text) + if(ret!=ESP_OK)return ret; + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; + unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); ++ return ts_ws_result_publish(r,peers,n); ++} ++esp_err_t ts_ws_result_publish(ts_ws_reservation_t *r,const ts_ws_peer_t *peers,unsigned n) ++{ ++ esp_err_t ret=ESP_OK; + for(unsigned i=0;i=r->count || r->slots[i]<0)return ESP_ERR_INVALID_STATE; + portENTER_CRITICAL(&s_lock);s_deliveries[r->slots[i]].peer=peers[i];portEXIT_CRITICAL(&s_lock); +@@ -589,3 +623,27 @@ uint32_t ts_ws_transport_retry_ms(void) + portEXIT_CRITICAL(&s_lock); + return delta>0 ? (uint32_t)((delta+999)/1000) : 0; + } ++ ++esp_err_t ts_ws_power_reserve(bool tick,ts_ws_reservation_t *r) ++{ ++ *r=(ts_ws_reservation_t){0}; ++ ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); ++ if(!n)return ESP_OK; ++ esp_err_t ret=reserve_kind(peers,n,tick?MSG_POWER_TICK:MSG_POWER,TS_WS_POWER_BYTES,r); ++ portENTER_CRITICAL(&s_lock); ++ if(ret==ESP_OK)s_tx_stats.power_accepted++;else s_tx_stats.power_rejected++; ++ portEXIT_CRITICAL(&s_lock); ++ return ret; ++} ++esp_err_t ts_ws_power_publish(ts_ws_reservation_t *r,const char *text) ++{ ++ if(!r->message)return ESP_OK; /* no recipients at admission */ ++ esp_err_t ret=ts_ws_reserved_text(r,text); ++ if(ret!=ESP_OK)return ret; ++ for(unsigned i=0;icount;i++) { ++ esp_err_t result=ts_ws_reserved_submit(r,i,0,0,NULL,NULL); ++ if(result!=ESP_OK){ret=result;portENTER_CRITICAL(&s_lock);s_tx_stats.power_failed++;portEXIT_CRITICAL(&s_lock);} ++ } ++ return ret; ++} +diff --git a/tests/ws_subscriptions/README.md b/tests/ws_subscriptions/README.md +index 55a2244..60fcbfb 100644 +--- a/tests/ws_subscriptions/README.md ++++ b/tests/ws_subscriptions/README.md +@@ -24,3 +24,14 @@ Mock success of `httpd_ws_send_frame_async` means only success at that API bound + - `bash tests/ws_subscriptions/run_reviewer_baseline.sh`:使用归档和 SHA-256 复现五项未修复行为,退出 0 表示反例成立。 + - `bash tests/ws_subscriptions/run_reviewer.sh`:完整生产 manager/transport/event C + 自动提取的当前 WebUI/HTTP/服务/核心函数,验证暂停/排空、会话就绪、日志代次、聚合停止重试、主题公平性和联合资源预算。SSH/设备/SDK 是模拟,未执行远端操作。 + - 修复记录:`docs/repair/ws-subscriptions/reviewer-fixes/README.md`。 ++ ++## F1/F2 后续修复 ++ ++```sh ++bash tests/ws_subscriptions/run_f1_f2.sh --baseline ++bash tests/ws_subscriptions/run_f1_f2.sh ++``` ++ ++第一条校验本轮冻结的真实工作区源码,并用相同 F1/F2 断言确认旧行为失败;成功退出只表示反例成立。第二条执行当前完整 transport/manager 与提取的真实 Shell、exec 输出/终态和保护事件调用方,覆盖入队/发送失败、迟到结算、身份隔离、部分失败、独立容量、停止交错和持续竞争。两者均不连接设备。SDK cJSON 可用 `IDF_PATH` 指定,编译器可由标准 `CC` 环境变量指定。 ++ ++后续 CI 可在已有 ESP-IDF 源码准备好后安装 C 编译器和 ASan/UBSan,设置 `IDF_PATH`,依次执行 `run_host.sh`、`run_reviewer.sh` 和 `run_f1_f2.sh`。基线重放可作为单独的证据任务。本轮未修改 CI 工作流。详见 `docs/repair/ws-f1-f2/README.md`。 +diff --git a/tests/ws_subscriptions/run_reviewer.sh b/tests/ws_subscriptions/run_reviewer.sh +index fce67fb..90f3a47 100644 +--- a/tests/ws_subscriptions/run_reviewer.sh ++++ b/tests/ws_subscriptions/run_reviewer.sh +@@ -9,7 +9,7 @@ python3 - "$build" <<'PY' + from pathlib import Path + import sys,re + s=Path('components/ts_webui/src/ts_webui_ws.c').read_text() +-names=['ts_webui_log_stream_enable','has_log_clients','update_log_stream_state','set_client_role','ssh_terminal_done','ssh_generation_valid','ssh_status_valid','ssh_request_error','ssh_send_status','ssh_send_output','ssh_poll_task','ssh_cleanup','handle_ssh_connect','start_terminal_session','ts_webui_ws_stop','ssh_exec_terminal_publish','ws_handler'] ++names=['ts_webui_log_stream_enable','has_log_clients','update_log_stream_state','set_client_role','ssh_terminal_done','ssh_generation_valid','ssh_status_valid','ssh_request_error','ssh_send_status','ssh_output_done','ssh_terminal_flush','ssh_send_output','ssh_poll_task','ssh_cleanup','handle_ssh_connect','start_terminal_session','ts_webui_ws_stop','ssh_exec_output_done','ssh_exec_stream_publish','ssh_exec_terminal_flush','ssh_exec_terminal_publish','ws_handler'] + parts=[] + for name in names: + m=re.search(r'^(?:static )?(?:esp_err_t|bool|void) '+name+r'\([^;]*?\)\n\{',s,re.M);assert m,name +diff --git a/tests/ws_subscriptions/stubs/platform.h b/tests/ws_subscriptions/stubs/platform.h +index 5292501..08732ef 100644 +--- a/tests/ws_subscriptions/stubs/platform.h ++++ b/tests/ws_subscriptions/stubs/platform.h +@@ -52,7 +52,7 @@ static inline bool esp_timer_is_active(esp_timer_handle_t p) {return p->active;} + #ifndef TEST_REAL_EVENT + typedef const char *ts_event_base_t; + typedef void *ts_event_handler_handle_t; +-typedef struct {void*data;size_t data_size;} ts_event_t; ++typedef struct {void*data;size_t data_size;int id;} ts_event_t; + #define TS_EVENT_BASE_SYSTEM "system" + #define TS_EVENT_BASE_DEVICE_MON "device" + #define TS_EVENT_BASE_OTA "ota" +diff --git a/tests/ws_subscriptions/test_init.c b/tests/ws_subscriptions/test_init.c +index b8784f7..8de18f9 100644 +--- a/tests/ws_subscriptions/test_init.c ++++ b/tests/ws_subscriptions/test_init.c +@@ -22,6 +22,9 @@ static int ts_ws_subscriptions_init(void){return fail_stage==3?ESP_ERR_NO_MEM:ES + static esp_err_t ts_webui_ws_stop(httpd_handle_t server); + static int manager_stop_result,barrier_result,tx_stop_result,tx_stop_calls; + static bool owner_context,s_exec_running,s_ssh_poll_alive,cleanup_finishes; ++static atomic_bool s_exec_result_active,s_exec_output_failed,s_exec_terminal_ready; ++static atomic_uint s_ssh_output_pending,s_ssh_result_pending; ++static atomic_bool s_exec_terminal_claimed; + static atomic_uint s_exec_creators; + bool ts_ws_transport_in_context(void){return owner_context;} + static esp_err_t ts_ws_subscriptions_deinit(void){return manager_stop_result;} +diff --git a/tests/ws_subscriptions/test_manager.c b/tests/ws_subscriptions/test_manager.c +index 389b8e7..a881ab9 100644 +--- a/tests/ws_subscriptions/test_manager.c ++++ b/tests/ws_subscriptions/test_manager.c +@@ -35,6 +35,7 @@ static void(*delay_hook)(void); + static void(*api_hook)(void); + static bool queue_fail, immediate, send_fail, task_fail, api_business_error; + static unsigned shutdowns; ++static int sent_fd,send_fail_fd=-1; + int test_shutdown(int fd,int how){(void)how;assert(fd>0);shutdowns++;return 0;} + static void(*wait_hook)(void); + static const char *barrier_name; +@@ -51,7 +52,7 @@ unsigned ulTaskNotifyTake(int clear,TickType_t ticks) {(void)clear;(void)ticks;a + void vTaskDelete(TaskHandle_t t) {(void)t;} + void vTaskDelay(TickType_t t) {test_now+=(int64_t)t*1000;if(delay_hook)delay_hook();} + int httpd_ws_get_fd_info(httpd_handle_t h,int fd) {(void)h;(void)fd;return HTTPD_WS_CLIENT_WEBSOCKET;} +-int httpd_ws_send_frame_async(httpd_handle_t h,int fd,httpd_ws_frame_t*f) {(void)h;assert(fd>=0&&fd<32);frames[fd]++;if(sent_hook && !send_fail)sent_hook(f);memcpy(payloads[fd],f->payload,f->len);payloads[fd][f->len]=0;return send_fail?ESP_FAIL:0;} ++int httpd_ws_send_frame_async(httpd_handle_t h,int fd,httpd_ws_frame_t*f) {(void)h;assert(fd>=0&&fd<32);frames[fd]++;sent_fd=fd;if(sent_hook && !send_fail && send_fail_fd!=fd)sent_hook(f);memcpy(payloads[fd],f->payload,f->len);payloads[fd][f->len]=0;return send_fail || send_fail_fd==fd?ESP_FAIL:0;} + int httpd_queue_work(httpd_handle_t h,void(*fn)(void*),void*a) {(void)h;if(queue_fail)return ESP_FAIL;if(immediate) {TaskHandle_t saved=current;current=(void*)3;fn(a);current=saved;}else{assert(queued<64);queue[queued++]=(typeof(queue[0])){fn,a};}return 0;} + int ts_api_call(const char*method,const cJSON*p,ts_api_result_t*r) {(void)p;for(int i=0;i<7;i++)if(!strcmp(metrics[i],method))reads[i]++;if(api_hook)api_hook();r->data=cJSON_CreateObject();r->message=malloc(8);r->code=api_business_error?1:0;return 0;} + static void pump(void) { +@@ -160,7 +161,9 @@ int main(void) { + char *big=malloc(TS_WS_LEGACY_BYTES);memset(big,'x',TS_WS_LEGACY_BYTES); + ts_ws_message_t *large=ts_ws_message_text(big,TS_WS_LEGACY_BYTES-1);assert(large);assert(!ts_ws_message_text(big,TS_WS_LEGACY_BYTES));ts_ws_message_release(large);free(big); + ts_ws_message_t *one=ts_ws_message_text("{}",2);assert(one); +- for(int i=0;ipayload,match))observed_topics[i]++; + } + } ++ ++#ifndef WS_REVIEWER_NO_MAIN + int main(void){ + cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); +- start();open_peer(1);open_peer(2);assert(ts_ws_result_reserve(4096,&s_exec_terminal)==0);s_exec_running=true;delay_hook=progress; ++ start();open_peer(1);open_peer(2);s_exec_terminal_claimed=false;assert(ts_ws_result_reserve(4096,&s_exec_terminal)==0);s_exec_running=true;delay_hook=progress; + assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);delay_hook=NULL; + assert(s_worker && s_state==DRAINING); + reqs[1].method=1;incoming="{\"type\":\"ping\"}";current=(void*)3; +@@ -182,11 +193,11 @@ int main(void){ + ts_ws_message_t *full1=ts_ws_message_text("full1",5),*full2=ts_ws_message_text("full2",5);assert(full1&&full2); + ssh_send_output("payload",7);assert(s_ssh_state==SSH_TERMINAL && !s_ssh_running); + poll_exit();current=(void*)1;ts_ws_message_release(full1);ts_ws_message_release(full2);pump(); +- assert(strstr(payloads[1],"SSH output delivery failed") && !s_ssh_session && !s_ssh_poll_alive); ++ assert(strstr(payloads[1],"SSH output delivery incomplete") && !s_ssh_session && !s_ssh_poll_alive); + finish(); + puts("PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid"); + +- start();open_peer(1);assert(ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal)==0); ++ start();open_peer(1);s_exec_terminal_claimed=false;assert(ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal)==0); + m1=ts_ws_message_text("one",3);m2=ts_ws_message_text("two",3);assert(m1&&m2); + open_peer(2);a=frames[1];b=frames[2]; + ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\",\"session_id\":7}",7); +@@ -212,8 +223,10 @@ int main(void){ + test_now+=10000000;before=total_reads();run_batch();assert(total_reads()==before); + ts_ws_reservation_release(&reserved);run_batch();pump();assert(total_reads()>before); + char*large=malloc(TS_WS_LEGACY_BYTES);memset(large,'x',TS_WS_LEGACY_BYTES); +- m1=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);m2=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);assert(m1&&m2);free(large); ++ m1=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);m2=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-TS_WS_POWER_BUDGET-1);assert(m1&&m2);free(large); + test_now+=10000000;before=total_reads();run_batch();assert(total_reads()==before); + ts_ws_message_release(m1);ts_ws_message_release(m2);run_batch();pump();assert(total_reads()>before);finish(); + puts("PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity"); + } ++ ++#endif +--- /dev/null ++++ b/tests/ws_subscriptions/run_f1_f2.sh +@@ -0,0 +1,49 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++build=$(mktemp -d /tmp/ts-ws-f1-f2.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++if [[ "${1:-}" == "--baseline" ]]; then ++ tar -xzf docs/repair/ws-f1-f2/pre-fix-source.tar.gz -C "$build" ++ python3 - "$build" <<'HASH' ++import json,hashlib,sys ++from pathlib import Path ++for name,want in json.loads(Path('docs/repair/ws-f1-f2/baseline.json').read_text())['sha256'].items(): ++ assert hashlib.sha256((Path(sys.argv[1])/name).read_bytes()).hexdigest()==want,name ++print('Frozen production snapshot hashes verified') ++HASH ++ # Current assertions/harness against unchanged frozen production sources. ++ cp tests/ws_subscriptions/{test_f1_f2.c,test_reviewer.c,run_f1_f2.sh} "$build/tests/ws_subscriptions/" ++ cp tests/ws_subscriptions/stubs/platform.h "$build/tests/ws_subscriptions/stubs/" ++ if bash "$build/tests/ws_subscriptions/run_f1_f2.sh" > "$build/red.txt" 2>&1; then ++ cat "$build/red.txt"; echo 'Unexpected baseline PASS'; exit 1 ++ fi ++ cat "$build/red.txt" ++ grep -q 'F1 assertion:.*FAIL' "$build/red.txt" ++ grep -q 'F2 assertion:.*FAIL' "$build/red.txt" ++ if grep -Eq 'error:|Assertion failed|Sanitizer' "$build/red.txt"; then exit 1; fi ++ echo 'CONFIRMED: both failures are behavioral assertions, not compilation or cleanup failures' ++ exit 0 ++fi ++export DEVELOPER_DIR=/Library/Developer/CommandLineTools ++cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" ++python3 - "$build" <<'PY' ++from pathlib import Path ++import re,sys ++script=Path('tests/ws_subscriptions/run_reviewer.sh').read_text() ++code=script.split("<<'PY'\n",1)[1].split('\nPY',1)[0] ++exec(compile(code,'extract-reviewer','exec')) ++s=Path('components/ts_webui/src/ts_webui_ws.c').read_text();parts=[] ++for name in ['power_state_to_string','power_policy_event_handler','ts_webui_broadcast','simple_pattern_match','ssh_exec_output_callback']: ++ m=re.search(r'^(?:static )?(?:const char \*|void |esp_err_t |bool )'+name+r'\([^;]*?\)\n\{',s,re.M);assert m,name ++ parts.append(s[m.start():s.index('\n}',m.start())+2]) ++Path(sys.argv[1],'power_caller.inc').write_text('\n'.join(parts)) ++PY ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" -I"$build" tests/ws_subscriptions/test_f1_f2.c "$cjson/cJSON.c" -o "$build/f1f2" ++failed=0 ++scenarios="f1 f2" ++if grep -q TS_WS_POWER_SLOTS components/ts_webui/include/ts_ws_transport.h; then scenarios="$scenarios late early identity exec continuous power_retry capacity retry_limit stop timeout class power_order fair"; fi ++for scenario in $scenarios; do ++ if ! "$build/f1f2" "$scenario"; then failed=1; fi ++done ++exit "$failed" +--- /dev/null ++++ b/tests/ws_subscriptions/test_f1_f2.c +@@ -0,0 +1,152 @@ ++#define WS_REVIEWER_NO_MAIN ++#include "test_reviewer.c" ++/* Actual power callback, with only the power status input type replaced. */ ++typedef enum {TS_POWER_POLICY_STATE_NORMAL,TS_POWER_POLICY_STATE_LOW_VOLTAGE,TS_POWER_POLICY_STATE_SHUTDOWN,TS_POWER_POLICY_STATE_PROTECTED,TS_POWER_POLICY_STATE_RECOVERY}ts_power_policy_state_t; ++enum {TS_POWER_POLICY_EVENT_STATE_CHANGED,TS_POWER_POLICY_EVENT_LOW_VOLTAGE,TS_POWER_POLICY_EVENT_COUNTDOWN_TICK,TS_POWER_POLICY_EVENT_SHUTDOWN_START,TS_POWER_POLICY_EVENT_PROTECTED,TS_POWER_POLICY_EVENT_RECOVERY_START,TS_POWER_POLICY_EVENT_RECOVERY_COMPLETE,TS_POWER_POLICY_EVENT_DEBUG_TICK}; ++typedef struct {ts_power_policy_state_t state;float current_voltage;unsigned countdown_remaining_sec,protection_count;}ts_power_policy_status_t; ++#include ++#include ++static struct {bool collect_output,match_found,fail_matched,expect_matched,stop_on_match;char *output_buffer,*fail_pattern,*expect_pattern,*extract_pattern,*extracted_value;size_t output_capacity,output_len;char var_name[64];ts_ssh_config_t config;} *s_exec_params; ++static bool s_exec_cancel_requested; ++static void *s_exec_session; ++typedef struct{char source_id[64],name[96];int flags;struct {int type;char str_val[256];int int_val;}value;}ts_auto_variable_t; ++#define TS_AUTO_VAL_STRING 1 ++#define TS_AUTO_VAL_INT 2 ++static int ts_variable_upsert(ts_auto_variable_t*v){(void)v;return 0;} ++static void ts_ssh_abort(void*s){(void)s;assert(!"network delivery must not abort remote commands");} ++#define malloc tracked_malloc ++#define heap_caps_malloc test_heap_malloc ++#define free tracked_free ++#include "power_caller.inc" ++#undef free ++#undef malloc ++#undef heap_caps_malloc ++static unsigned powers,errors; ++#ifdef TS_WS_POWER_SLOTS ++static unsigned outputs[32],terminals[32],logs,protection_order[64],protection_n; ++static void observe_all(httpd_ws_frame_t*f){observe_topic(f);const char*p=(const char*)f->payload;if(strstr(p,"power_event")){powers++;if(protection_n<64){cJSON*j=cJSON_Parse(p);protection_order[protection_n++]=cJSON_GetObjectItem(j,"protection_count")->valueint;cJSON_Delete(j);}}if(strstr(p,"ssh_exec_output")||strstr(p,"ssh_output"))outputs[sent_fd]++;if(strstr(p,"ssh_exec_error")||strstr(p,"\"status\":\"error\""))errors++;if(strstr(p,"ssh_exec_done")||strstr(p,"ssh_exec_error"))terminals[sent_fd]++;if(!strcmp(p,"log"))logs++;} ++static void exec_begin(void){s_exec_session_id++;s_exec_output_failed=false;s_exec_terminal_claimed=false;s_exec_terminal_ready=false;s_exec_result_active=true;assert(!s_exec_output_pending);assert(ts_ws_result_reserve(4096,&s_exec_terminal)==0);} ++#endif ++static void observe_power(httpd_ws_frame_t*f){if(strstr((char*)f->payload,"power_event"))powers++;if(strstr((char*)f->payload,"\"status\":\"error\""))errors++;} ++static void power_change(void){ts_power_policy_status_t s={.state=TS_POWER_POLICY_STATE_PROTECTED,.current_voltage=10.0f,.protection_count=1};ts_event_t e={.id=TS_POWER_POLICY_EVENT_PROTECTED,.data=&s,.data_size=sizeof(s)};power_policy_event_handler(&e,NULL);} ++int main(int argc,char**argv){ ++ assert(argc==2);cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks);start();open_peer(1);sent_hook=observe_power; ++ if(!strcmp(argv[1],"f1")){ ++ connect_request(false,false);queue_fail=true;ssh_send_output("chunk",5);queue_fail=false;test_now+=100000;progress();pump(); ++ bool handled=!s_ssh_running && errors>0; ++ printf("F1 assertion: accepted SSH output enqueue failure reaches session and error frame: %s\n",handled?"PASS":"FAIL (stream still normal / no error frame)"); ++ s_ssh_running=false;poll_exit();current=(void*)1;finish();return handled?0:1; ++ } ++ if(!strcmp(argv[1],"f2")){ ++ ts_ws_peer_t p;assert(ts_ws_peer_get((void*)11,1,&p));ts_ws_peer_log_level(p,5); ++ httpd_ws_frame_t f={.type=1,.payload=(uint8_t*)"log",.len=3};assert(ts_ws_transport_log(&f,1)==0);assert(ts_ws_transport_log(&f,1)==0); ++ power_change();pump();bool handled=powers==1; ++ printf("F2 assertion: protection transition survives ordinary log pool saturation: %s\n",handled?"PASS":"FAIL (no protection frame)");finish();return handled?0:1; ++ } ++#ifdef TS_WS_POWER_SLOTS ++ sent_hook=observe_all; ++ if(!strcmp(argv[1],"late")){ ++ connect_request(false,false); ++ ts_ws_message_t*m=ts_ws_message_text("block",5);assert(ts_ws_transport_submit(s_ssh_peer,m,0,0,NULL,NULL)==0);ts_ws_message_release(m); ++ ssh_send_output("out",3);assert(s_ssh_output_pending==1);ssh_send_status("closed","normal close");assert(s_ssh_terminal_ready && s_ssh_result_pending); ++ sdk_one();queue_fail=true;worker_step();assert(s_ssh_output_failed && !s_ssh_output_pending);queue_fail=false;test_now+=100000;progress();pump(); ++ assert(errors==1 && !strstr(payloads[1],"normal close"));s_ssh_running=false;poll_exit();current=(void*)1;finish(); ++ puts("PASS late SSH rejection: prior output settles before terminal; closed becomes explicit incomplete-output error");return 0; ++ } ++ if(!strcmp(argv[1],"early")){ ++ connect_request(false,false);immediate=true;uint64_t settled=s_tx_stats.settled; ++ ssh_send_output("ok",2);assert(!s_ssh_output_pending && s_tx_stats.settled==settled+1 && outputs[1]==1); ++ send_fail=true;ssh_send_output("fail",4);send_fail=false;immediate=false; ++ assert(s_tx_stats.settled==settled+2 && s_ssh_output_failed && !s_ssh_running && !s_ssh_output_pending); ++ poll_exit();current=(void*)1;finish();puts("PASS callback-before-return and actual send failure: exactly one settlement, no reference leak");return 0; ++ } ++ if(!strcmp(argv[1],"identity")){ ++ connect_request(false,false);unsigned old=s_ssh_generation; ++ ssh_send_output("old",3);close_peer(1);open_peer(1); ++ connect_request(false,false);assert(s_ssh_generation==old); /* retained old producer blocks replacement */ ++ pump();assert(s_ssh_output_failed && outputs[1]==0);poll_exit();current=(void*)1; ++ connect_request(false,false);assert(s_ssh_generation>old && s_ssh_running); ++ ssh_output_done(old,1,ESP_FAIL);assert(s_ssh_running && !s_ssh_output_failed); /* delayed old notification is fenced */ ++ s_ssh_running=false;poll_exit();current=(void*)1;pump();finish();puts("PASS old connection/generation cannot receive old output or fail replacement session");return 0; ++ } ++ if(!strcmp(argv[1],"exec")){ ++ open_peer(2);exec_begin();unsigned sid=s_exec_session_id;uint64_t settled_before=s_tx_stats.settled; ++ ssh_exec_output_callback("part",4,false,(void*)(uintptr_t)sid);assert(s_exec_output_pending==2); ++ ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\"}",sid);assert(s_exec_terminal_ready); ++ sdk_one();assert(outputs[1]==1 && !terminals[1]);queue_fail=true;worker_step();queue_fail=false; ++ assert(s_exec_output_failed && !s_exec_output_pending);test_now+=100000;worker_step();pump(); ++ assert(outputs[1]==1 && outputs[2]==0 && terminals[1]==1 && terminals[2]==1 && errors==2);assert(s_tx_stats.settled==settled_before+4); ++ assert(strstr(payloads[1],"not confirmed"));finish(); ++ puts("PASS actual exec callback: partial target failure is independent; no successful output replay and no false done");return 0; ++ } ++ if(!strcmp(argv[1],"continuous")){ ++ exec_begin();queue_fail=true;ssh_exec_output_callback("chunk",5,false,(void*)(uintptr_t)s_exec_session_id);queue_fail=false; ++ test_now+=100000;progress();pump();assert(errors==1 && !s_exec_output_pending && !s_exec_result_active); ++ unsigned frames_before=frames[1];ssh_exec_output_callback("later",5,false,(void*)(uintptr_t)s_exec_session_id);ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\"}",s_exec_session_id);pump();assert(frames[1]==frames_before && !s_exec_cancel_requested); ++ finish();puts("PASS continuous exec: observation reports incomplete immediately; no remote abort/replay or later normal completion");return 0; ++ } ++ if(!strcmp(argv[1],"power_retry")){ ++ open_peer(2);queue_fail=true;power_change();assert(s_tx_stats.power_accepted==1 && !powers); ++ worker_step();queue_fail=false;test_now+=100000;worker_step();sdk_one();worker_step();sdk_one();assert(powers==2); ++ send_fail_fd=2;power_change();pump();send_fail_fd=-1;assert(powers==3 && s_tx_stats.power_failed==1);finish(); ++ puts("PASS protection queue recovery without new messages; partial socket failure never replays successful recipient");return 0; ++ } ++ if(!strcmp(argv[1],"capacity")){ ++ ts_ws_peer_t p;assert(ts_ws_peer_get((void*)11,1,&p)); ++ ts_ws_message_t*m=ts_ws_message_text("log",3);for(unsigned i=0;i=TS_WS_TOPIC_TX_SLOTS&&i0);}assert(powers>0&&logs>0);finish();puts("PASS bounded sustained log/protection/topic competition: all eligible classes progress");return 0; ++ } ++#endif ++ return 2; ++} diff --git a/docs/repair/ws-f1-f2/diff-check.txt b/docs/repair/ws-f1-f2/diff-check.txt new file mode 100644 index 0000000..f132957 --- /dev/null +++ b/docs/repair/ws-f1-f2/diff-check.txt @@ -0,0 +1,2 @@ +git diff --check +exit: 0 diff --git a/docs/repair/ws-f1-f2/final-manifest.json b/docs/repair/ws-f1-f2/final-manifest.json new file mode 100644 index 0000000..7ab1cbb --- /dev/null +++ b/docs/repair/ws-f1-f2/final-manifest.json @@ -0,0 +1,41 @@ +{ + "created_at": "2026-09-25T04:47:06.036356+08:00", + "head": "bb0958c902d37ddc2b2deb36291b5439c0964160", + "branch": "fix/v0.5.2-reliability-and-prompts", + "patch_scope": "Code and tests relative to bb0958c; report and evidence stored separately.", + "source_sha256": { + "components/ts_webui/include/ts_ws_transport.h": "dc7917b1d09c2569ce0d49f024f6a0db27924f81b1d58cdf0a7a7c51afeebdd6", + "components/ts_webui/src/ts_webui_ws.c": "ea02c3ca56a37f8a4c850467c204246d774f80eb8386a970ab82a1ec24f8095c", + "components/ts_webui/src/ts_ws_transport.c": "954540760b95964947bfbd3d2c5165aec8322c4e962ad48a806ff849475adabd", + "tests/ws_subscriptions/README.md": "e2a186d0cc38c5a2df86207cde9f371365b95e678908b15943a7556fe57e5ada", + "tests/ws_subscriptions/run_reviewer.sh": "17ea374c62bdbe2f8314423fe8538f864f0c9678405f13f1feb23e4ac22462d9", + "tests/ws_subscriptions/stubs/platform.h": "de005401b26f9dce9028db4bbc656ea72e55730535769be4ddf31ccec072c2dc", + "tests/ws_subscriptions/test_init.c": "c79aca85e117cb6fc34f3f493dc6d6d6083a0eb1488ba00abfcbeff903a96870", + "tests/ws_subscriptions/test_manager.c": "bc51e67c9c51c66780a8e980f5cbb93d7773fe5b9abce038d206f6d65ab0a23d", + "tests/ws_subscriptions/test_reviewer.c": "baedff8fca5d4ee62ccbf8d11dd4277d218b974ecacc9a6b55c2bf76f945653b", + "tests/ws_subscriptions/run_f1_f2.sh": "b07f3e0e40267a244515524f560b72276e8a23567ca96ec467787594cf4e4b3e", + "tests/ws_subscriptions/test_f1_f2.c": "bda86a05b53a88441d653d0374d2d19b3d5ef24528e7b9f9577ae4bd4b03ce21" + }, + "evidence_sha256": { + "prompts.txt": "253d906e036eab1f2ae5af7a7284f75f6f1f23012808b463aa9f03da6a56f29b", + "changes.patch": "d2b59a98e9d602b442c36a38a5b95f9002a9eeed88269759a3d4f8f4ffb7ab63", + "before.txt": "3beada5c6bb83d79e253bc8051c74a718fa472ebfc7a2250b1d92dca38898dca", + "runtime.txt": "f300e6d09f01acebc6d725ea5377e878f60d09db17464819d9306a0156817e96", + "after.txt": "2bd288d785066c1064363e5425e65d449113070a8e51b020c15ae7e85cb3cf7e", + "build.txt": "54bfa36fbefd1205856011dd2934ed6581e1a46756bcd397187af40ac5a8518d", + "host.txt": "fde8084a35208ab61ec026c7c1bc29578b75b5b92584c5b70f7a430bd1a9a907", + "certificate.txt": "d3e446956791a6ec5d2a6b2235eaffcc0c45cb6ed4f2cd32eae130bb57f7dd21", + "README.md": "4a75b822edf869245629eb5d0f05c32d796a404a1e69919d61f7fcff6d546855", + "browser.txt": "e685cd2c0801baa441fa5ca304f3a68d23d2fed4a7a4d2c0ea0cd1f87b5320de", + "reviewer.txt": "e1a7c52fb704d7010a8efd00488f46738f22ea275cd26cb59d49c8d0b316c60c", + "baseline.json": "b8c2f4ab4249bb0153a8560d4714c6fcbbc326861fd9d56c8d3d240949e30b41", + "pre-fix-source.tar.gz": "640e6527ecda3c892f2eb42aeb34c1dd1285f6ddc1b93ae68fd27eda840f3ba0", + "diff-check.txt": "2d0582f56d02ef3b69ef68368f867be3298b1bf7ee9ffb8ae2d05378c7cd097d", + "resources.txt": "8e01df723dd6673c4b48afa11fcc6ad831e222177130b7f3bcd1bc38031cbfdc" + }, + "build_binaries": { + "/tmp/tianshan-ws-build/build/TianShanOS.bin": "b5c7317017d6ae3de811af4278221f505496d15a6da17a7e513fc1bbfc8a5f6c", + "/tmp/tianshan-ws-build/build/www.bin": "cdce507bebb727bd65136aa8d3687d9d09651c1f1ea2286fb3fe2e87fa4f30c5", + "/tmp/tianshan-ws-build/build/ota_data_initial.bin": "7d2c7ac4888bfd75cd5f56e8d61f69595121183afc81556c876732fd3782c62f" + } +} diff --git a/docs/repair/ws-f1-f2/host.txt b/docs/repair/ws-f1-f2/host.txt new file mode 100644 index 0000000..377bb50 --- /dev/null +++ b/docs/repair/ws-f1-f2/host.txt @@ -0,0 +1,25 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket stop: manager/barrier failures propagate, active SSH creation/execution retained, poller timeout retained, transport drain retry and HTTPD self-wait rejected +PASS actual SSH creation wrappers: concurrent builder rejected and stop admission closes without invoking the remote-operation implementation +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-f1-f2/pr-update-gate.md b/docs/repair/ws-f1-f2/pr-update-gate.md new file mode 100644 index 0000000..97ff41b --- /dev/null +++ b/docs/repair/ws-f1-f2/pr-update-gate.md @@ -0,0 +1,11 @@ +# F1/F2 提交前审查 + +结论:可以推送。用户已明确授权更新原 PR #42。本轮基于 `bb0958c` 提交,不合并、不发布或操作设备。 + +复查了消息类别与准入、同步拒绝和异步结算、发布引用、目标身份、Shell/exec 终态顺序、保护事件回调、重试上限及停止依赖保留。当前源码与 final-manifest.json 所列构建输入哈希一致,构建二进制哈希也一致。未发现本轮范围内阻止推送的问题;不宣称无其他缺陷。 + +提交前再次执行 `bash tests/ws_subscriptions/run_f1_f2.sh`、`bash tests/ws_subscriptions/run_reviewer.sh` 和 `python3 tests/release/test_release.py`,均通过。日志为 pr-update-regression.txt、pr-update-reviewer.txt、pr-update-release.txt。其余回归及固件编译复用同一源码的本轮证据,详见 README.md。 + +暂存范围为 F1/F2 源码、测试、冻结基线/证据及更新后的中文发布说明。原 output/、tmp/ 和 docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt 排除并保留。版本与工作流未改。历史 changes.patch 保留原上下文空格,不作为源码空格错误处理;当前源码、测试和文档另行进行暂存差异检查。 + +边界:主机 SDK/RTOS/设备响应模拟及本地浏览器回归不等于真实设备验收。慢连接、双核并发、保护负载、长期堆与栈水位仍待实机。保护通知有界而非无限无损;exec 网页观察失败不等于远端操作被取消。旧修复记录中的未提交状态是当时事实,此后按新授权更新 PR。 diff --git a/docs/repair/ws-f1-f2/pr-update-regression.txt b/docs/repair/ws-f1-f2/pr-update-regression.txt new file mode 100644 index 0000000..6d212e3 --- /dev/null +++ b/docs/repair/ws-f1-f2/pr-update-regression.txt @@ -0,0 +1,23 @@ +F1 assertion: accepted SSH output enqueue failure reaches session and error frame: PASS +F2 assertion: protection transition survives ordinary log pool saturation: PASS +PASS late SSH rejection: prior output settles before terminal; closed becomes explicit incomplete-output error +PASS callback-before-return and actual send failure: exactly one settlement, no reference leak +PASS old connection/generation cannot receive old output or fail replacement session +PASS actual exec callback: partial target failure is independent; no successful output replay and no false done +PASS continuous exec: observation reports incomplete immediately; no remote abort/replay or later normal completion +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS busy stop retains output and protection drain; retry releases dependencies +PASS timeout stop continues output/protection drain without new messages; retry completes +PASS completion callbacks do not reclassify SSH output or subject it to telemetry cancellation +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-f1-f2/pr-update-release.txt b/docs/repair/ws-f1-f2/pr-update-release.txt new file mode 100644 index 0000000..e76e6ef --- /dev/null +++ b/docs/repair/ws-f1-f2/pr-update-release.txt @@ -0,0 +1,5 @@ +... +---------------------------------------------------------------------- +Ran 3 tests in 0.003s + +OK diff --git a/docs/repair/ws-f1-f2/pr-update-reviewer.txt b/docs/repair/ws-f1-f2/pr-update-reviewer.txt new file mode 100644 index 0000000..dc04122 --- /dev/null +++ b/docs/repair/ws-f1-f2/pr-update-reviewer.txt @@ -0,0 +1,17 @@ +PASS R1: busy stop retains real worker; final fanout drains with no new producer message +PASS R1 timeout: handler-barrier and transport-drain failures retain worker; accepted fanout progresses before retry +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid +PASS R2 exec: admitted result reservation survives ordinary saturation and preserves recipients at completion +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-f1-f2/pre-fix-source.tar.gz b/docs/repair/ws-f1-f2/pre-fix-source.tar.gz new file mode 100644 index 0000000..63d3321 Binary files /dev/null and b/docs/repair/ws-f1-f2/pre-fix-source.tar.gz differ diff --git a/docs/repair/ws-f1-f2/prompts.txt b/docs/repair/ws-f1-f2/prompts.txt new file mode 100644 index 0000000..39e69ba --- /dev/null +++ b/docs/repair/ws-f1-f2/prompts.txt @@ -0,0 +1,51 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (16.525584ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.348584ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (8.070792ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.294875ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.985042ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.780042ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (6.274084ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.813459ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.760792ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.338916ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.819666ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.813792ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (5.246709ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.621166ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.930541ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.565416ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.672417ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.900291ms) +✔ en-US: batch deletion all / partial / no success with business errors (6.354167ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (6.550666ms) +✔ en-US: file names are text; upload/verification/apply remain separate (6.103041ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (9.191542ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.851291ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.155459ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (5.576125ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.47125ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (4.806667ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (6.679917ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (5.252583ms) +✔ en-US: upload and download aggregates cover all success and all failure (5.244125ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (5.232791ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (5.1295ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (5.420292ms) +✔ zh-CN: unknown stop result never escalates to forced termination (6.239042ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (5.05475ms) +✔ en-US: unknown stop result never escalates to forced termination (4.964709ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.8155ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.097333ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 267.763958 diff --git a/docs/repair/ws-f1-f2/resources.txt b/docs/repair/ws-f1-f2/resources.txt new file mode 100644 index 0000000..98864b1 --- /dev/null +++ b/docs/repair/ws-f1-f2/resources.txt @@ -0,0 +1,18 @@ +/Users/massif/TianshanOS/components/ts_webui/src/ts_webui_ws.c:155:13:power_policy_event_handler 736 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_webui_ws.c:236:13:ssh_terminal_flush 192 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_webui_ws.c:227:13:ssh_output_done 32 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_webui_ws.c:1790:13:ssh_exec_terminal_flush 272 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_webui_ws.c:1584:13:ssh_exec_output_callback 528 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_subscriptions.c:197:13:run_batch 3360 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:234:13:settle 48 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:288:18:publish_delivery 32 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:627:11:ts_ws_power_reserve 288 static +ts_webui_ws.o +00000000 00000100 b s_exec_result_peers +00000000 00000088 b s_exec_terminal +00000000 00000088 b s_ssh_terminal +ts_ws_subscriptions.o +ts_ws_transport.o +00000000 00002100 b s_deliveries +00000000 0000012c b s_messages +00000000 00001400 b s_power_payloads diff --git a/docs/repair/ws-f1-f2/reviewer.txt b/docs/repair/ws-f1-f2/reviewer.txt new file mode 100644 index 0000000..dc04122 --- /dev/null +++ b/docs/repair/ws-f1-f2/reviewer.txt @@ -0,0 +1,17 @@ +PASS R1: busy stop retains real worker; final fanout drains with no new producer message +PASS R1 timeout: handler-barrier and transport-drain failures retain worker; accepted fanout progresses before retry +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid +PASS R2 exec: admitted result reservation survives ordinary saturation and preserves recipients at completion +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-f1-f2/runtime.txt b/docs/repair/ws-f1-f2/runtime.txt new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ws-f1-f2/runtime.txt @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ws-j1/README.md b/docs/repair/ws-j1/README.md new file mode 100644 index 0000000..9690543 --- /dev/null +++ b/docs/repair/ws-j1/README.md @@ -0,0 +1,70 @@ +# J1 电源告警显示修复 + +结论:**J1 已修复,本轮要求的本地验证通过;真实设备与远端终端显示仍待实机验收。** 本轮不对其他系统功能作无缺陷承诺。 + +实施基线 HEAD:`8ad39a9b1ca39d225f94fb4db602fb2ee7438d09`,分支 `fix/v0.5.2-reliability-and-prompts`。开始时无 tracked 修改,原有 output/、tmp/ 和 runtime-repair 下未跟踪文件未纳入修复。实施阶段未提交、推送、更新 PR、合并、发布或操作设备。用户随后授权更新 PR;提交前审查见 [publication-gate.md](publication-gate.md)。 + +## 修改范围 + +| 文件 | J1 必需的改动 | +|---|---| +| components/ts_webui/web/js/terminal.js | 仅 handlePowerEvent:销毁或无 terminal 时返回;完全采用指定 canRestoreLocalInput 条件。只有本地可交互时走原恢复代码,否则仅另起一行输出原告警 | +| components/ts_webui/web/index.html | 沿用 TS_ASSET_VERSION 和查询参数方式,缓存标识更新到 20260927-power-prompt;无布局改动 | +| tests/prompts/regression.test.cjs | 在既有 Node 测试中追加中英文状态矩阵,执行生产消息分发与已注册输入回调 | +| tests/prompts/project-cross.cjs | 在原跨层链中追加 J1:真实 C 保护通知 → 生产 socket 消费 → 实际输入 → 原 C Shell → 正常退出与回收;原 H1 等断言保留 | +| tests/ws_subscriptions/test_project.c | 仅测试夹具增加 power 命令,调用生产 power_policy_event_handler;输出原 op identity 供断言归属,不修改任何生产后端 | +| tests/ws_subscriptions/verify_project_assets.py | 原校验器硬编码旧 cache key,改为与当前源 index 标识比对;增加既有风格的结果目录参数,避免覆盖 v3 历史证据 | + +[实际 diff](changes.patch)、[前后输入哈希及范围记录](inputs.json)。已比较 terminal.js 修改前后:handlePowerEvent 之外完全一致;index 只替换缓存标识。后端 SSH、WS/operation、队列、引用、取消、采样、保护、版本和发布流程均未改。 + +## 行为与测试结果 + +修复前 J1 状态测试在活动 SSH 上失败:连续两次告警产生 8 次写入(包含清行、本地提示符/缓冲与光标),期望仅两次通知;实际 C 跨层反例也出现 4 次写入而不是一条通知。见 before-node.txt、before-cross.txt;这两项是业务断言失败,不是编译或环境失败。 + +| 场景 | 本次验证结果 | +|---|---| +| 本地 abcd 未提交、光标在第 2 位 | 连续告警均保留原 clear → 告警 → tianshan> abcd → 左移 2 位序列;字段不变,无自动提交;一次告警只恢复一次输入行 | +| 活动 SSH,连续告警 | 通知可见且另起一行;不清远端行、不写本地提示符、不回放 abcd、不用本地位置移动光标;状态及发送列表不变 | +| 告警后继续输入 | 实际 onData 产生 ssh_input;跨层返回真实 C handler 后,原 operation identity 不变且 driver 写入增加一次 | +| 正常退出 | 实际退出键产生 ssh_disconnect;请求后以及 disconnecting 阶段无本地提示符,收到 closed 后才恢复;真实 C channel 最终为零,原全部资源结算断言通过 | +| connecting / disconnecting / restoring | 均不恢复本地输入行,告警不改变任何指定状态字段;原受限输入仍被忽略 | +| 连接断开 / socket 非 OPEN / socket 不存在 | 不恢复本地提示符、不触发恢复或业务请求 | +| destroyed / terminal 不存在 | 直接调用告警处理也不访问销毁对象、不抛异常、不发请求 | +| 已从 SSH 正常关闭后再次告警 | 根据当时真实本地状态恢复提示符、缓冲与光标,不沿用先前 SSH 状态 | +| 原事件筛选 | countdown 31 不显示;30 及原保护通知仍显示。告警文本、颜色、翻译和 switch 分支无修改 | + +状态测试使用实际 terminal.js 和实际注册输入回调。Chrome 跨层加载真实入口、语言包和 socket 消费者;SDK 最终消息 bytes 来自生产 C 保护处理及传输层。SDK/网络、libssh2 外边界和 xterm 渲染仍为既有测试替身,不等于实机运行。 + +## 本次执行记录 + +以下均为本轮重新执行,未用历史结果代替: + +- `node --test --test-name-pattern=J1 tests/prompts/regression.test.cjs`:中英文 J1 状态/输入/筛选断言通过,见 after-node.txt。 +- `npm test --prefix tests/prompts`:40 项通过,包含原回归及新增 J1;见 webui-node.txt。 +- `npm run test:browser --prefix tests/prompts`:原浏览器回归 38 项通过,见 webui-browser.txt。 +- `CROSS_LANGUAGE=zh-CN/en-US node tests/prompts/project-cross.cjs`:两种语言均通过,保留原 H1、归属、生命周期等断言;见 cross-node-results.json 及对应消息证据。 +- 上一条加 `--browser`:两种语言 Chrome 跨层通过,见 browser-results.json。 +- 使用本次构建目录的 `PROJECT_WEB_ROOT=.../web_optimized`,再次运行双语 `project-cross.cjs --browser`:通过,见 optimized-results.json。证明打包后的消费者也具有 J1 行为。 +- `git diff --check`:通过。 + +C 夹具使用 `IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf`、`DEVELOPER_DIR=/Library/Developer/CommandLineTools`。跨层记录通过 `CROSS_OUTPUT` 保存到本目录。没有新增测试框架或变更依赖版本;独立控制/取消全套主机入口本轮未额外重跑,相关生产代码未修改,且现有断言未删改。 + +## 本次构建及静态资源 + +固定 ESP-IDF v5.5.2 / ESP32-S3,独立目录:`/tmp/tianshan-j1-build/build`。 + +```sh +# 在固定 SDK export.sh 环境中 +idf.py -B /tmp/tianshan-j1-build/build -D SDKCONFIG=/tmp/tianshan-j1-build/sdkconfig build +IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf \ +V3_BUILD=/tmp/tianshan-j1-build/build V3_RESULTS=docs/repair/ws-j1 \ +python3 tests/ws_subscriptions/verify_project_assets.py +``` + +构建成功;应用镜像 0x215120,应用分区约 31% 剩余。见 build.log。该日志包含 SDK 的刷机用法提示,**没有执行刷机命令**。 + +[assets.json](assets.json) 记录源码、优化文件、gzip、固件和 www 的哈希。JS 语法检查、gzip 解压一致、新 cache key 检查通过;用验证后的优化目录重新生成 SPIFFS,与实际 www.bin 逐字节一致。中英文优化资源跨层回放同时通过。支持固件/www 配套更新并刷新页面;未验证设备实际浏览器缓存升级过程。 + +## 未执行及验收边界 + +本轮要求的本地项目均已执行,无缺少环境而跳过的必需项目。未授权实机,因此未测试设备上的真实电源告警、真实 SSH/xterm 光标呈现、网络时序及缓存升级。实机应确认本地行中输入、活动 SSH 连续告警、输入与退出、连接过渡状态和更新后资源缓存的同样行为。没有发送远端重绘、回车或查询;远端提示符仍由远端输出决定。 diff --git a/docs/repair/ws-j1/after-node.txt b/docs/repair/ws-j1/after-node.txt new file mode 100644 index 0000000..b189c8e --- /dev/null +++ b/docs/repair/ws-j1/after-node.txt @@ -0,0 +1,10 @@ +✔ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (15.974625ms) +✔ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (5.388041ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 63.776708 diff --git a/docs/repair/ws-j1/assets-check.txt b/docs/repair/ws-j1/assets-check.txt new file mode 100644 index 0000000..4c96e4a --- /dev/null +++ b/docs/repair/ws-j1/assets-check.txt @@ -0,0 +1 @@ +PASS optimized syntax, gzip identity, cache key, and byte-identical SPIFFS reconstruction diff --git a/docs/repair/ws-j1/assets.json b/docs/repair/ws-j1/assets.json new file mode 100644 index 0000000..9f8cd48 --- /dev/null +++ b/docs/repair/ws-j1/assets.json @@ -0,0 +1,41 @@ +{ + "index.html": { + "source_sha256": "ad6e0ed5e11c34b8797877be912ea2e42a5dc632b6cdae1b915222ea6ea6315b", + "optimized_sha256": "ad6e0ed5e11c34b8797877be912ea2e42a5dc632b6cdae1b915222ea6ea6315b", + "gzip_sha256": "cb9d819710e9d2f39b409dd62b60c6d717bcb8f2f7e38fdf6f3aa8427896c90c", + "optimized_bytes": 26685 + }, + "js/terminal.js": { + "source_sha256": "8bfa9622f6fafb8cf1c88ab1081b47fa32df0fdd1814acdf67bd7708326ec0a1", + "optimized_sha256": "541da884de013c0028d59b06db25c9f3a399a4fe955e9998d52c8330a8ed6551", + "gzip_sha256": "cdeaedeffea9ecc872c3ee6ca4c8a9b004d02258c6bfb7b858d183d71d92f64b", + "optimized_bytes": 20034 + }, + "js/lang/zh-CN.js": { + "source_sha256": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "optimized_sha256": "81b0fed5b0ac73d51d9c37204c9f62e035a79bbf5b5610d37fc8a936faf9fd64", + "gzip_sha256": "219dd01fe4313897ed2bc739fcf9cd4cd862995647bb5cadd30361490a326bbf", + "optimized_bytes": 137314 + }, + "js/lang/en-US.js": { + "source_sha256": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "optimized_sha256": "e9963046086616fecc9ba662df94e736a98c1430865e0caa47292b3690ca0ad0", + "gzip_sha256": "1e3f3e14884f76f4301275a8b4ba96951ca79f39b70b3d0b082faa0012f6776c", + "optimized_bytes": 143161 + }, + "build": { + "TianShanOS.bin": { + "sha256": "a26590324dd730d33c3ab1ea2149fcbe3d53fb7d698ca9c211e4bcd95e737bc5", + "bytes": 2183456 + }, + "www.bin": { + "sha256": "80457119106c753b8273aaec7c9a8e3e640bbac60447b6059d8b42e084baa132", + "bytes": 3145728 + }, + "TianShanOS.elf": { + "sha256": "0d50d71dd4d38fca6f786565106ea77cc9ca14d9523d8a2fc61fd11bd9fd1436", + "bytes": 18286808 + } + }, + "spiffs_regeneration": "byte-identical from verified optimized directory" +} \ No newline at end of file diff --git a/docs/repair/ws-j1/before-cross.txt b/docs/repair/ws-j1/before-cross.txt new file mode 100644 index 0000000..8abb7dd --- /dev/null +++ b/docs/repair/ws-j1/before-cross.txt @@ -0,0 +1,13 @@ +AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + +4 !== 1 + + at main (/Users/massif/TianshanOS/tests/prompts/project-cross.cjs:58:9) + at process.processTicksAndRejections (node:internal/process/task_queues:105:5) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 4, + expected: 1, + operator: 'strictEqual', + diff: 'simple' +} diff --git a/docs/repair/ws-j1/before-node.txt b/docs/repair/ws-j1/before-node.txt new file mode 100644 index 0000000..3850809 --- /dev/null +++ b/docs/repair/ws-j1/before-node.txt @@ -0,0 +1,46 @@ +✖ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (19.361916ms) +✖ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (4.840625ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 0 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 68.423167 + +✖ failing tests: + +test at tests/prompts/regression.test.cjs:174:2 +✖ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (19.361916ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 8 !== 2 + + at TestContext. (/Users/massif/TianshanOS/tests/prompts/regression.test.cjs:191:11) + at async Test.run (node:internal/test_runner/test:1113:7) + at async startSubtestAfterBootstrap (node:internal/test_runner/harness:358:3) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 8, + expected: 2, + operator: 'strictEqual', + diff: 'simple' + } + +test at tests/prompts/regression.test.cjs:174:2 +✖ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (4.840625ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 8 !== 2 + + at TestContext. (/Users/massif/TianshanOS/tests/prompts/regression.test.cjs:191:11) + at async Test.run (node:internal/test_runner/test:1113:7) + at async Test.processPendingSubtests (node:internal/test_runner/test:788:7) { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 8, + expected: 2, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/docs/repair/ws-j1/browser-results.json b/docs/repair/ws-j1/browser-results.json new file mode 100644 index 0000000..d4d5efa --- /dev/null +++ b/docs/repair/ws-j1/browser-results.json @@ -0,0 +1,30 @@ +[ + { + "command": [ + "npm", + "run", + "test:browser", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "language": "zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + }, + { + "language": "en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ws-j1/build.log b/docs/repair/ws-j1/build.log new file mode 100644 index 0000000..0cb95c7 --- /dev/null +++ b/docs/repair/ws-j1/build.log @@ -0,0 +1,1673 @@ +Executing action: all (aliases: build) +Running cmake in directory /private/tmp/tianshan-j1-build/build +Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DPYTHON=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python -DESP_PLATFORM=1 -DSDKCONFIG=/tmp/tianshan-j1-build/sdkconfig -DCCACHE_ENABLE=0 /Users/massif/TianshanOS"... +-- Found Python3: /opt/anaconda3/bin/python3.12 (found version "3.12.4") found components: Interpreter +-- IDF_TARGET is not set, guessed 'esp32s3' from sdkconfig '/tmp/tianshan-j1-build/sdkconfig' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +NOTICE: +Following dependencies have new versions available: +Dependency "espressif/libpng": "1.6.54" -> "1.6.58~2" +Dependency "espressif/mdns": "1.9.1" -> "1.13.1" +Dependency "espressif/zlib": "1.3.1" -> "1.3.2~1" +Consider running "idf.py update-dependencies" to update your lock file. +NOTICE: Processing 7 dependencies: +NOTICE: [1/7] espressif/esp_jpeg (1.3.1) +NOTICE: [2/7] espressif/esp_websocket_client (1.5.0) +NOTICE: [3/7] espressif/led_strip (3.0.3) +NOTICE: [4/7] espressif/libpng (1.6.54) +NOTICE: [5/7] espressif/mdns (1.9.1) +NOTICE: [6/7] espressif/zlib (1.3.1) +NOTICE: [7/7] idf (5.5.2) +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-j1-build/sdkconfig +Loading defaults file /Users/massif/TianshanOS/sdkconfig.defaults... +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:54 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:56 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:64 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:66 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:82 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:84 line was updated to # === L2 NVS 加密配置(HMAC 方案)===n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:159 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:161 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:170 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:172 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:182 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:184 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:193 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:195 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:227 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmperfm1lr0:229 line was updated to # ============================================================================n +-- Compiler supported targets: xtensa-esp-elf +-- Found Python3: /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python (found version "3.12.4") found components: Interpreter +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS - Success +-- USING O3 +-- App "TianShanOS" version: 0.5.2+8ad39a9d.09271926 +-- Adding linker script /tmp/tianshan-j1-build/build/esp-idf/esp_system/ld/memory.ld +-- Adding linker script /tmp/tianshan-j1-build/build/esp-idf/esp_system/ld/sections.ld.in +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Web optimization enabled (minify + gzip) +-- Components: app_trace app_update bootloader bootloader_support bt ch405labs_esp_libssh2 cmock console cxx driver efuse esp-tls esp_adc esp_app_format esp_bootloader_format esp_coex esp_common esp_driver_ana_cmpr esp_driver_bitscrambler esp_driver_cam esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_isp esp_driver_jpeg esp_driver_ledc esp_driver_mcpwm esp_driver_parlio esp_driver_pcnt esp_driver_ppa esp_driver_rmt esp_driver_sdio esp_driver_sdm esp_driver_sdmmc esp_driver_sdspi esp_driver_spi esp_driver_touch_sens esp_driver_tsens esp_driver_twai esp_driver_uart esp_driver_usb_serial_jtag esp_eth esp_event esp_gdbstub esp_hid esp_http_client esp_http_server esp_https_ota esp_https_server esp_hw_support esp_lcd esp_local_ctrl esp_mm esp_netif esp_netif_stack esp_partition esp_phy esp_pm esp_psram esp_ringbuf esp_rom esp_security esp_system esp_timer esp_vfs_console esp_wifi espcoredump espressif__esp_jpeg espressif__esp_websocket_client espressif__led_strip espressif__libpng espressif__mdns espressif__zlib esptool_py fatfs freertos hal heap http_parser idf_test ieee802154 json log lwip main mbedtls mqtt newlib nvs_flash nvs_sec_provider openthread partition_table perfmon protobuf-c protocomm pthread rt sdmmc soc spi_flash spiffs tcp_transport touch_element ts_api ts_auth_layout ts_automation ts_cert ts_config ts_config_pack ts_console ts_core ts_drivers ts_event ts_hal ts_https ts_jsonpath ts_led ts_log ts_mempool ts_net ts_ota ts_pki_client ts_security ts_service ts_storage ts_webui ulp unity usb vfs wear_levelling wifi_provisioning wpa_supplicant xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/app_trace /Users/massif/esp/v5.5.2/esp-idf/components/app_update /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/bt /Users/massif/TianshanOS/components/ch405labs_esp_libssh2 /Users/massif/esp/v5.5.2/esp-idf/components/cmock /Users/massif/esp/v5.5.2/esp-idf/components/console /Users/massif/esp/v5.5.2/esp-idf/components/cxx /Users/massif/esp/v5.5.2/esp-idf/components/driver /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp-tls /Users/massif/esp/v5.5.2/esp-idf/components/esp_adc /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_coex /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ana_cmpr /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_bitscrambler /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_cam /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_dac /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gpio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gptimer /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2c /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2s /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_isp /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_jpeg /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ledc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_mcpwm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_parlio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_pcnt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ppa /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_rmt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdspi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_spi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_touch_sens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_tsens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_twai /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_uart /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_usb_serial_jtag /Users/massif/esp/v5.5.2/esp-idf/components/esp_eth /Users/massif/esp/v5.5.2/esp-idf/components/esp_event /Users/massif/esp/v5.5.2/esp-idf/components/esp_gdbstub /Users/massif/esp/v5.5.2/esp-idf/components/esp_hid /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_client /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_ota /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_lcd /Users/massif/esp/v5.5.2/esp-idf/components/esp_local_ctrl /Users/massif/esp/v5.5.2/esp-idf/components/esp_mm /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif_stack /Users/massif/esp/v5.5.2/esp-idf/components/esp_partition /Users/massif/esp/v5.5.2/esp-idf/components/esp_phy /Users/massif/esp/v5.5.2/esp-idf/components/esp_pm /Users/massif/esp/v5.5.2/esp-idf/components/esp_psram /Users/massif/esp/v5.5.2/esp-idf/components/esp_ringbuf /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esp_timer /Users/massif/esp/v5.5.2/esp-idf/components/esp_vfs_console /Users/massif/esp/v5.5.2/esp-idf/components/esp_wifi /Users/massif/esp/v5.5.2/esp-idf/components/espcoredump /Users/massif/TianshanOS/managed_components/espressif__esp_jpeg /Users/massif/TianshanOS/managed_components/espressif__esp_websocket_client /Users/massif/TianshanOS/managed_components/espressif__led_strip /Users/massif/TianshanOS/managed_components/espressif__libpng /Users/massif/TianshanOS/managed_components/espressif__mdns /Users/massif/TianshanOS/managed_components/espressif__zlib /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/fatfs /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/heap /Users/massif/esp/v5.5.2/esp-idf/components/http_parser /Users/massif/esp/v5.5.2/esp-idf/components/idf_test /Users/massif/esp/v5.5.2/esp-idf/components/ieee802154 /Users/massif/esp/v5.5.2/esp-idf/components/json /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/lwip /Users/massif/TianshanOS/main /Users/massif/esp/v5.5.2/esp-idf/components/mbedtls /Users/massif/esp/v5.5.2/esp-idf/components/mqtt /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/nvs_flash /Users/massif/esp/v5.5.2/esp-idf/components/nvs_sec_provider /Users/massif/esp/v5.5.2/esp-idf/components/openthread /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/perfmon /Users/massif/esp/v5.5.2/esp-idf/components/protobuf-c /Users/massif/esp/v5.5.2/esp-idf/components/protocomm /Users/massif/esp/v5.5.2/esp-idf/components/pthread /Users/massif/esp/v5.5.2/esp-idf/components/rt /Users/massif/esp/v5.5.2/esp-idf/components/sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/spiffs /Users/massif/esp/v5.5.2/esp-idf/components/tcp_transport /Users/massif/esp/v5.5.2/esp-idf/components/touch_element /Users/massif/TianshanOS/components/ts_api /Users/massif/TianshanOS/components/ts_auth_layout /Users/massif/TianshanOS/components/ts_automation /Users/massif/TianshanOS/components/ts_cert /Users/massif/TianshanOS/components/ts_core/ts_config /Users/massif/TianshanOS/components/ts_config_pack /Users/massif/TianshanOS/components/ts_console /Users/massif/TianshanOS/components/ts_core /Users/massif/TianshanOS/components/ts_drivers /Users/massif/TianshanOS/components/ts_core/ts_event /Users/massif/TianshanOS/components/ts_hal /Users/massif/TianshanOS/components/ts_https /Users/massif/TianshanOS/components/ts_jsonpath /Users/massif/TianshanOS/components/ts_led /Users/massif/TianshanOS/components/ts_core/ts_log /Users/massif/TianshanOS/components/ts_mempool /Users/massif/TianshanOS/components/ts_net /Users/massif/TianshanOS/components/ts_ota /Users/massif/TianshanOS/components/ts_pki_client /Users/massif/TianshanOS/components/ts_security /Users/massif/TianshanOS/components/ts_core/ts_service /Users/massif/TianshanOS/components/ts_storage /Users/massif/TianshanOS/components/ts_webui /Users/massif/esp/v5.5.2/esp-idf/components/ulp /Users/massif/esp/v5.5.2/esp-idf/components/unity /Users/massif/esp/v5.5.2/esp-idf/components/usb /Users/massif/esp/v5.5.2/esp-idf/components/vfs /Users/massif/esp/v5.5.2/esp-idf/components/wear_levelling /Users/massif/esp/v5.5.2/esp-idf/components/wifi_provisioning /Users/massif/esp/v5.5.2/esp-idf/components/wpa_supplicant /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- +-- ╔═══════════════════════════════════════════════════════════╗ +-- ║ TianShanOS v0.5.2+8ad39a9d.09271926 ║ +-- ║ ESP32 Rack Management Operating System ║ +-- ╚═══════════════════════════════════════════════════════════╝ +-- +-- Version: 0.5.2+8ad39a9d.09271926 +-- Major: 0 +-- Minor: 5 +-- Patch: 2 +-- Build: 8ad39a9d.09271926 +-- +-- Target: esp32s3 +-- Build type: +-- +-- Configuring done (6.9s) +-- Generating done (0.5s) +-- Build files have been written to: /tmp/tianshan-j1-build/build +Running ninja in directory /private/tmp/tianshan-j1-build/build +Executing "ninja all"... +[1/1343] Generating project_elf_src_esp32s3.c +[2/1343] Generating ../../ota_data_initial.bin +[3/1343] Generating /tmp/tianshan-j1-build/build/esp-idf/esp_system/ld/memory.ld linker script... +[4/1343] Generating /tmp/tianshan-j1-build/build/esp-idf/esp_system/ld/sections.ld.in linker script... +[5/1343] Copying web assets to build directory +[6/1343] Generating ../../partition_table/partition-table.bin +Partition table binary generated. Contents: +******************************************************************************* +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs,data,nvs,0x9000,48K, +nvs_keys,data,nvs_keys,0x15000,4K, +otadata,data,ota,0x16000,8K, +phy_init,data,phy,0x18000,4K, +ota_0,app,ota_0,0x20000,3M, +ota_1,app,ota_1,0x320000,3M, +storage,data,spiffs,0x620000,512K, +www,data,spiffs,0x6a0000,3M, +fatfs,data,fat,0x9a0000,64K, +******************************************************************************* +[7/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_header.c.obj +[8/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_utils.c.obj +[9/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/util/ctrl_sock.c.obj +[10/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_auth.c.obj +[11/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_uri.c.obj +[12/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport.c.obj +[13/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_main.c.obj +[14/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_internal.c.obj +[15/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_sess.c.obj +[16/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_ws.c.obj +[17/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_socks_proxy.c.obj +[18/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_txrx.c.obj +[19/1343] Building C object esp-idf/esp_https_ota/CMakeFiles/__idf_esp_https_ota.dir/src/esp_https_ota.c.obj +[20/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/system_layer/esp_psram.c.obj +[21/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/xip_impl/mmu_psram_flash.c.obj +[22/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_parse.c.obj +[23/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ssl.c.obj +[24/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/esp32s3/esp_psram_impl_octal.c.obj +[25/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali.c.obj +[26/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp_adc_cal_common_legacy.c.obj +[27/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali_curve_fitting.c.obj +[28/1343] Linking C static library esp-idf/esp_https_ota/libesp_https_ota.a +[29/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/esp32s3/curve_fitting_coefficients.c.obj +[30/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp-tls-crypto/esp_tls_crypto.c.obj +[31/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_platform_port.c.obj +[32/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp32s3/esp_adc_cal_legacy.c.obj +[33/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_oneshot.c.obj +[34/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_common.c.obj +[35/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ws.c.obj +[36/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/gdma/adc_dma.c.obj +[37/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_monitor.c.obj +[38/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_filter.c.obj +[39/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_error_capture.c.obj +[40/1343] Linking C static library esp-idf/esp_http_server/libesp_http_server.a +[41/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_continuous.c.obj +[42/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/sigma_delta_legacy.c.obj +[43/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rtc_temperature_legacy.c.obj +[44/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/esp_http_client.c.obj +[45/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_dma_legacy.c.obj +[46/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/touch_sensor_common.c.obj +[47/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_legacy.c.obj +[48/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls.c.obj +[49/1343] Linking C static library esp-idf/esp_http_client/libesp_http_client.a +[50/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/timer_legacy.c.obj +[51/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/pcnt_legacy.c.obj +[52/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai.c.obj +[53/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_mbedtls.c.obj +[54/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/esp32s3/touch_sensor.c.obj +[55/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/twai/twai.c.obj +[56/1343] Linking C static library esp-idf/tcp_transport/libtcp_transport.a +[57/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/i2c/i2c.c.obj +[58/1343] Building C object esp-idf/http_parser/CMakeFiles/__idf_http_parser.dir/http_parser.c.obj +[59/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_common.c.obj +[60/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder.c.obj +[61/1343] Linking C static library esp-idf/esp_psram/libesp_psram.a +[62/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai_onchip.c.obj +[63/1343] Building C object esp-idf/esp_driver_tsens/CMakeFiles/__idf_esp_driver_tsens.dir/src/temperature_sensor.c.obj +[64/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_bytes.c.obj +[65/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/i2s_legacy.c.obj +[66/1343] Building C object esp-idf/esp_driver_sdm/CMakeFiles/__idf_esp_driver_sdm.dir/src/sdm.c.obj +[67/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_common.c.obj +[68/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_slave.c.obj +[69/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_simple.c.obj +[70/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_crc.c.obj +[71/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_copy.c.obj +[72/1343] Linking C static library esp-idf/esp_adc/libesp_adc.a +[73/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/mcpwm_legacy.c.obj +[74/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_transaction.c.obj +[75/1343] Building C object esp-idf/esp_driver_ledc/CMakeFiles/__idf_esp_driver_ledc.dir/src/ledc.c.obj +[76/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_master.c.obj +[77/1343] Linking C static library esp-idf/esp-tls/libesp-tls.a +[78/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_transaction.c.obj +[79/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_init.c.obj +[80/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_host.c.obj +[81/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_mmc.c.obj +[82/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sd_pwr_ctrl/sd_pwr_ctrl.c.obj +[83/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_io.c.obj +[84/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_cmd.c.obj +[85/1343] Linking C static library esp-idf/http_parser/libhttp_parser.a +[86/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_rx.c.obj +[87/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_common.c.obj +[88/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_sd.c.obj +[89/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rmt_legacy.c.obj +[90/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_platform.c.obj +[91/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_std.c.obj +[92/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_com.c.obj +[93/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cmpr.c.obj +[94/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_pdm.c.obj +[95/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_tdm.c.obj +[96/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_fault.c.obj +[97/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_sync.c.obj +[98/1343] Linking C static library esp-idf/driver/libdriver.a +[99/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_oper.c.obj +[100/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_host.c.obj +[101/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_tx.c.obj +[102/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub-entry.S.obj +[103/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cap.c.obj +[104/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/packet.c.obj +[105/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub_transport.c.obj +[106/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/xt_debugexception.S.obj +[107/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_timer.c.obj +[108/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_common.c.obj +[109/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_gen.c.obj +[110/1343] Linking C static library esp-idf/esp_driver_twai/libesp_driver_twai.a +[111/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub.c.obj +[112/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub_xtensa.c.obj +[113/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/lib_printf.c.obj +[114/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/mesh_event.c.obj +[115/1343] Linking C static library esp-idf/esp_driver_ledc/libesp_driver_ledc.a +[116/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj +[117/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default_ap.c.obj +[118/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig.c.obj +[119/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_netif.c.obj +[120/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/regulatory/esp_wifi_regulatory.c.obj +[121/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default.c.obj +[122/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug_diagram.c.obj +[123/1343] Building C object esp-idf/esp_driver_pcnt/CMakeFiles/__idf_esp_driver_pcnt.dir/src/pulse_cnt.c.obj +[124/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/esp32s3/esp_coex_adapter.c.obj +[125/1343] Linking C static library esp-idf/esp_driver_i2c/libesp_driver_i2c.a +[126/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave.c.obj +[127/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug.c.obj +[128/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave_hd.c.obj +[129/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32s3/esp_adapter.c.obj +[130/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig_ack.c.obj +[131/1343] Linking C static library esp-idf/esp_driver_sdm/libesp_driver_sdm.a +[132/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_common.c.obj +[133/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/os_xtensa.c.obj +[134/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_1x.c.obj +[135/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/eloop.c.obj +[136/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/comeback_token.c.obj +[137/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/pmksa_cache_auth.c.obj +[138/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/sta_info.c.obj +[139/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth_ie.c.obj +[140/1343] Linking C static library esp-idf/esp_driver_tsens/libesp_driver_tsens.a +[141/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_master.c.obj +[142/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ap_config.c.obj +[143/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/dragonfly.c.obj +[144/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-siv.c.obj +[145/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/bitfield.c.obj +[146/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-kdf.c.obj +[147/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_11.c.obj +[148/1343] Linking C static library esp-idf/esp_driver_rmt/libesp_driver_rmt.a +[149/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_group5.c.obj +[150/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_ops.c.obj +[151/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/wpa_common.c.obj +[152/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_groups.c.obj +[153/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-gcm.c.obj +[154/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ccmp.c.obj +[155/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-tlsprf.c.obj +[156/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ms_funcs.c.obj +[157/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tlsprf.c.obj +[158/1343] Linking C static library esp-idf/esp_driver_sdspi/libesp_driver_sdspi.a +[159/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-prf.c.obj +[160/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-tlsprf.c.obj +[161/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-prf.c.obj +[162/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth.c.obj +[163/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-prf.c.obj +[164/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tprf.c.obj +[165/1343] Linking C static library esp-idf/esp_driver_sdmmc/libesp_driver_sdmmc.a +[166/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/md4-internal.c.obj +[167/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_common/eap_wsc_common.c.obj +[168/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/chap.c.obj +[169/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae.c.obj +[170/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_common.c.obj +[171/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/ieee802_11_common.c.obj +[172/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap_common.c.obj +[173/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/mschapv2.c.obj +[174/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls.c.obj +[175/1343] Linking C static library esp-idf/sdmmc/libsdmmc.a +[176/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap.c.obj +[177/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_mschapv2.c.obj +[178/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_common.c.obj +[179/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls_common.c.obj +[180/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap.c.obj +[181/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/pmksa_cache.c.obj +[182/1343] Linking C static library esp-idf/esp_driver_i2s/libesp_driver_i2s.a +[183/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/base64.c.obj +[184/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_ttls.c.obj +[185/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/ext_password.c.obj +[186/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa_ie.c.obj +[187/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/common.c.obj +[188/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/uuid.c.obj +[189/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_pac.c.obj +[190/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpa_debug.c.obj +[191/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpabuf.c.obj +[192/1343] Linking C static library esp-idf/esp_driver_mcpwm/libesp_driver_mcpwm.a +[193/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast.c.obj +[194/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa2_api_port.c.obj +[195/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/json.c.obj +[196/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_build.c.obj +[197/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_process.c.obj +[198/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps.c.obj +[199/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_parse.c.obj +[200/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_common.c.obj +[201/1343] Linking C static library esp-idf/esp_driver_pcnt/libesp_driver_pcnt.a +[202/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_dev_attr.c.obj +[203/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa_main.c.obj +[204/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa.c.obj +[205/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpas_glue.c.obj +[206/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae_pk.c.obj +[207/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_enrollee.c.obj +[208/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_common.c.obj +[209/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_owe.c.obj +[210/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_eap_client.c.obj +[211/1343] Linking C static library esp-idf/esp_gdbstub/libesp_gdbstub.a +[212/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa3.c.obj +[213/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpsk.c.obj +[214/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_hostap.c.obj +[215/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wps.c.obj +[216/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls.c.obj +[217/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c.obj +[218/1343] Linking C static library esp-idf/esp_driver_spi/libesp_driver_spi.a +[219/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/rc4.c.obj +[220/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpbkdf2.c.obj +[221/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-wrap.c.obj +[222/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_defaults.c.obj +[223/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/tls_mbedtls.c.obj +[224/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/des-internal.c.obj +[225/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-unwrap.c.obj +[226/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c.obj +[227/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_objects.c.obj +[228/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_handlers.c.obj +[229/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-ccm.c.obj +[230/1343] Linking C static library esp-idf/esp_wifi/libesp_wifi.a +[231/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-ec.c.obj +[232/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_sntp.c.obj +[233/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip_defaults.c.obj +[234/1343] Linking C static library esp-idf/esp_coex/libesp_coex.a +[235/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj +[236/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj +[237/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/sntp/sntp.c.obj +[238/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/err.c.obj +[239/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj +[240/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj +[241/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/if_api.c.obj +[242/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netifapi.c.obj +[243/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netdb.c.obj +[244/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj +[245/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj +[246/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj +[247/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/sntp/sntp.c.obj +[248/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/init.c.obj +[249/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/def.c.obj +[250/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ip.c.obj +[251/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/mem.c.obj +[252/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/netbiosns/netbiosns.c.obj +[253/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj +[254/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/memp.c.obj +[255/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj +[256/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/dns.c.obj +[257/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/sys.c.obj +[258/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/stats.c.obj +[259/1343] Linking C static library esp-idf/wpa_supplicant/libwpa_supplicant.a +[260/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/netif.c.obj +[261/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj +[262/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/autoip.c.obj +[263/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/timeouts.c.obj +[264/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/raw.c.obj +[265/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj +[266/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/icmp.c.obj +[267/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_out.c.obj +[268/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/dhcp6.c.obj +[269/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj +[270/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/igmp.c.obj +[271/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj +[272/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_frag.c.obj +[273/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp.c.obj +[274/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_in.c.obj +[275/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ethip6.c.obj +[276/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/dhcp.c.obj +[277/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj +[278/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/icmp6.c.obj +[279/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/inet6.c.obj +[280/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj +[281/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_napt.c.obj +[282/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_frag.c.obj +[283/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_addr.c.obj +[284/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj +[285/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/auth.c.obj +[286/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif_fdb.c.obj +[287/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif.c.obj +[288/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-md5.c.obj +[289/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ccp.c.obj +[290/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-new.c.obj +[291/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/mld6.c.obj +[292/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/slipif.c.obj +[293/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap_ms.c.obj +[294/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eap.c.obj +[295/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/demand.c.obj +[296/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6.c.obj +[297/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ecp.c.obj +[298/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eui64.c.obj +[299/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/fsm.c.obj +[300/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipv6cp.c.obj +[301/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/lcp.c.obj +[302/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipcp.c.obj +[303/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/magic.c.obj +[304/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/mppe.c.obj +[305/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppapi.c.obj +[306/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppol2tp.c.obj +[307/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/multilink.c.obj +[308/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ppp.c.obj +[309/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppos.c.obj +[310/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppoe.c.obj +[311/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/nd6.c.obj +[312/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppcrypt.c.obj +[313/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/utils.c.obj +[314/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/upap.c.obj +[315/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/vj.c.obj +[316/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/tcp_isn_default.c.obj +[317/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/sockets_ext.c.obj +[318/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/lwip_default_hooks.c.obj +[319/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/debug/lwip_debug.c.obj +[320/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/des.c.obj +[321/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md5.c.obj +[322/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/arc4.c.obj +[323/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md4.c.obj +[324/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping.c.obj +[325/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/esp_ping.c.obj +[326/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/freertos/sys_arch.c.obj +[327/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/acd_dhcp_check.c.obj +[328/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/if_index.c.obj +[329/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/sha1.c.obj +[330/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32xx/vfs_lwip.c.obj +[331/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping_sock.c.obj +[332/1343] Linking C static library esp-idf/esp_netif/libesp_netif.a +[333/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/lib_printf.c.obj +[334/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/dhcpserver/dhcpserver.c.obj +[335/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/esp32s3/phy_init_data.c.obj +[336/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_connection_monitor.c.obj +[337/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj +[338/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/nullfs.c.obj +[339/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_eventfd.c.obj +[340/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_common.c.obj +[341/1343] Building C object esp-idf/esp_vfs_console/CMakeFiles/__idf_esp_vfs_console.dir/vfs_console.c.obj +[342/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/btbb_init.c.obj +[343/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag.c.obj +[344/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj +[345/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_vfs.c.obj +[346/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_semihost.c.obj +[347/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs.c.obj +[348/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_platform.cpp.obj +[349/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader.c.obj +[350/1343] Linking C static library esp-idf/lwip/liblwip.a +[351/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_aes.c.obj +[352/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition.cpp.obj +[353/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_xts_aes.c.obj +[354/1343] Linking C static library esp-idf/vfs/libvfs.a +[355/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_lookup.cpp.obj +[356/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/default_event_loop.c.obj +[357/1343] Linking C static library esp-idf/esp_vfs_console/libesp_vfs_console.a +[358/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event_private.c.obj +[359/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_wakeup.c.obj +[360/1343] Linking C static library esp-idf/esp_driver_usb_serial_jtag/libesp_driver_usb_serial_jtag.a +[361/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event.c.obj +[362/1343] Linking C static library esp-idf/esp_phy/libesp_phy.a +[363/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uhci.c.obj +[364/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_vfs.c.obj +[365/1343] Building C object esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj +[366/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer.c.obj +[367/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart.c.obj +[368/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_init.c.obj +[369/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer_common.c.obj +[370/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj +[371/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj +[372/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj +[373/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj +[374/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj +[375/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_exception_stubs.cpp.obj +[376/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_init.cpp.obj +[377/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_cond_var.c.obj +[378/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj +[379/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_local_storage.c.obj +[380/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_rwlock.c.obj +[381/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/init.c.obj +[382/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_guards.cpp.obj +[383/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_semaphore.c.obj +[384/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/abort.c.obj +[385/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/assert.c.obj +[386/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_item_hash_list.cpp.obj +[387/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/poll.c.obj +[388/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/heap.c.obj +[389/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_cxx_api.cpp.obj +[390/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/pthread.c.obj +[391/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/locks.c.obj +[392/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/random.c.obj +[393/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/getentropy.c.obj +[394/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_encrypted_partition.cpp.obj +[395/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/termios.c.obj +[396/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_locked.cpp.obj +[397/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_types.cpp.obj +[398/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/realpath.c.obj +[399/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/scandir.c.obj +[400/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/sysconf.c.obj +[401/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/syscalls.c.obj +[402/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_simple.cpp.obj +[403/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/time.c.obj +[404/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_page.cpp.obj +[405/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_pagemanager.cpp.obj +[406/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_syscalls.c.obj +[407/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/esp_time_impl.c.obj +[408/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/flockfile.c.obj +[409/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_init.c.obj +[410/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_manager.cpp.obj +[411/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/xtensa/stdatomic_s32c1i.c.obj +[412/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/newlib_init.c.obj +[413/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_storage.cpp.obj +[414/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj +[415/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj +[416/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj +[417/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_api.cpp.obj +[418/1343] Building ASM object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/portasm.S.obj +[419/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj +[420/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/app_startup.c.obj +[421/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_init.c.obj +[422/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/stdatomic.c.obj +[423/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/event_groups.c.obj +[424/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/timers.c.obj +[425/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_overlay_os_hook.c.obj +[426/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/freertos_compatibility.c.obj +[427/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions_event_groups.c.obj +[428/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/stream_buffer.c.obj +[429/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[430/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/port.c.obj +[431/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[432/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj +[433/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[434/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[435/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions.c.obj +[436/1343] Linking C static library esp-idf/nvs_flash/libnvs_flash.a +[437/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_ctrl_os.c.obj +[438/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/revision.c.obj +[439/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_gpio_reserve.c.obj +[440/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj +[441/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj +[442/1343] Linking C static library esp-idf/esp_event/libesp_event.a +[443/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mac_addr.c.obj +[444/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_clk_tree.c.obj +[445/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj +[446/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj +[447/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/io_mux.c.obj +[448/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj +[449/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sar_periph_ctrl_common.c.obj +[450/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_dma_utils.c.obj +[451/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_utils.c.obj +[452/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj +[453/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma_link.c.obj +[454/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj +[455/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_clk_tree_common.c.obj +[456/1343] Linking C static library esp-idf/esp_driver_uart/libesp_driver_uart.a +[457/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_mspi.c.obj +[458/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_usb.c.obj +[459/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modem.c.obj +[460/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_bus_lock.c.obj +[461/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_share_hw_ctrl.c.obj +[462/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_console.c.obj +[463/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/adc_share_hw_ctrl.c.obj +[464/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/systimer.c.obj +[465/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_event.c.obj +[466/1343] Linking C static library esp-idf/esp_ringbuf/libesp_ringbuf.a +[467/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_async_memcpy.c.obj +[468/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_wake_stub.c.obj +[469/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/deprecated/gdma_legacy.c.obj +[470/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_gpio.c.obj +[471/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[472/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/mspi_timing_tuning.c.obj +[473/1343] Linking C static library esp-idf/esp_driver_gptimer/libesp_driver_gptimer.a +[474/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[475/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clock_output.c.obj +[476/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/async_memcpy_gdma.c.obj +[477/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[478/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/power_supply/brownout.c.obj +[479/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[480/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[481/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_memprot_conv.c.obj +[482/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[483/1343] Linking C static library esp-idf/esp_timer/libesp_timer.a +[484/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_config.c.obj +[485/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_lock.c.obj +[486/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/sar_periph_ctrl.c.obj +[487/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma.c.obj +[488/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[489/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/init.c.obj +[490/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[491/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[492/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_hmac.c.obj +[493/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_periph_clk.c.obj +[494/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/lowpower/port/esp32s3/sleep_cpu.c.obj +[495/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_ds.c.obj +[496/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[497/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[498/1343] Linking C static library esp-idf/cxx/libcxx.a +[499/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[500/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[501/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c.obj +[502/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[503/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[504/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[505/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj +[506/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[507/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[508/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[509/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[510/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[511/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[512/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[513/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[514/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[515/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[516/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[517/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[518/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[519/1343] Linking C static library esp-idf/pthread/libpthread.a +[520/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[521/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[522/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[523/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[524/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[525/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/esp32s3/memory_layout.c.obj +[526/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_memprot.c.obj +[527/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[528/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/memory_layout_utils.c.obj +[529/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_timestamp.c.obj +[530/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj +[531/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[532/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[533/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/util.c.obj +[534/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_lock.c.obj +[535/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj +[536/1343] Linking C static library esp-idf/newlib/libnewlib.a +[537/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[538/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_init.c.obj +[539/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[540/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[541/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/log_level.c.obj +[542/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_write.c.obj +[543/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj +[544/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/linked_list/log_linked_list.c.obj +[545/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/tag_log_level.c.obj +[546/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/cache/log_binary_heap.c.obj +[547/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[548/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[549/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/color_hal.c.obj +[550/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[551/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[552/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[553/1343] Linking C static library esp-idf/freertos/libfreertos.a +[554/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_encrypt_hal_iram.c.obj +[555/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[556/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal.c.obj +[557/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj +[558/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal_iram.c.obj +[559/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal.c.obj +[560/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gpio_hal.c.obj +[561/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/timer_hal.c.obj +[562/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/clk_tree_hal.c.obj +[563/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rtc_io_hal.c.obj +[564/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal.c.obj +[565/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/tlsf/tlsf.c.obj +[566/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal_iram.c.obj +[567/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal_iram.c.obj +[568/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj +[569/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rmt_hal.c.obj +[570/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal.c.obj +[571/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/pcnt_hal.c.obj +[572/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mcpwm_hal.c.obj +[573/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uhci_hal.c.obj +[574/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_top.c.obj +[575/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdm_hal.c.obj +[576/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdmmc_hal.c.obj +[577/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_ahb_v1.c.obj +[578/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/lcd_hal.c.obj +[579/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpi_hal.c.obj +[580/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_oneshot_hal.c.obj +[581/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/twai_hal_v1.c.obj +[582/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/aes_hal.c.obj +[583/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal.c.obj +[584/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2s_hal.c.obj +[585/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal_common.c.obj +[586/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj +[587/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sha_hal.c.obj +[588/1343] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[589/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal.c.obj +[590/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal.c.obj +[591/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal_iram.c.obj +[592/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hmac_hal.c.obj +[593/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ds_hal.c.obj +[594/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_wrap_hal.c.obj +[595/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj +[596/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hd_hal.c.obj +[597/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sensor_hal.c.obj +[598/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cam_hal.c.obj +[599/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_serial_jtag_hal.c.obj +[600/1343] Linking C static library esp-idf/esp_security/libesp_security.a +[601/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/touch_sensor_hal.c.obj +[602/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal_iram.c.obj +[603/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sens_hal.c.obj +[604/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[605/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/xt_wdt_hal.c.obj +[606/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[607/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/rtc_cntl_hal.c.obj +[608/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[609/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_dwc_hal.c.obj +[610/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[611/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[612/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[613/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[614/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[615/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[616/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[617/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[618/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[619/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[620/1343] Linking C static library esp-idf/soc/libsoc.a +[621/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj +[622/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system_console.c.obj +[623/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_ipc.c.obj +[624/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/stack_check.c.obj +[625/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj +[626/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj +[627/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/system_time.c.obj +[628/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj +[629/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup.c.obj +[630/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj +[631/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/panic.c.obj +[632/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/xt_wdt.c.obj +[633/1343] Linking C static library esp-idf/heap/libheap.a +[634/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup_funcs.c.obj +[635/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_routines.S.obj +[636/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_handler.S.obj +[637/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_port.c.obj +[638/1343] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[639/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj +[640/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_handler_asm.S.obj +[641/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj +[642/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/image_process.c.obj +[643/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj +[644/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack_asm.S.obj +[645/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj +[646/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers_asm.S.obj +[647/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_ipc_isr.c.obj +[648/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack.c.obj +[649/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_arch.c.obj +[650/1343] Linking C static library esp-idf/log/liblog.a +[651/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/highint_hdl.S.obj +[652/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_stubs.c.obj +[653/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj +[654/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj +[655/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/reset_reason.c.obj +[656/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers.c.obj +[657/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/trax.c.obj +[658/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/apb_backup_dma.c.obj +[659/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_drivers.c.obj +[660/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_issi.c.obj +[661/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp32s3/spi_flash_oct_flash_init.c.obj +[662/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_hpm_enable.c.obj +[663/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/cache_err_int.c.obj +[664/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/system_internal.c.obj +[665/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic.c.obj +[666/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_boya.c.obj +[667/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_th.c.obj +[668/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_gd.c.obj +[669/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/clk.c.obj +[670/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_winbond.c.obj +[671/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic_opi.c.obj +[672/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_generic.c.obj +[673/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/memspi_host_driver.c.obj +[674/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/port/esp32s3/ext_mem_layout.c.obj +[675/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[676/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj +[677/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj +[678/1343] Linking C static library esp-idf/hal/libhal.a +[679/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/heap_align_hw.c.obj +[680/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_utils.c.obj +[681/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj +[682/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj +[683/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj +[684/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[685/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_msync.c.obj +[686/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj +[687/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[688/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[689/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_spi_init.c.obj +[690/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[691/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[692/1343] Linking C static library esp-idf/esp_rom/libesp_rom.a +[693/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[694/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_api.c.obj +[695/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[696/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[697/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[698/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[699/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[700/1343] Linking C static library esp-idf/esp_common/libesp_common.a +[701/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[702/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[703/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/secure_boot_secure_features.c.obj +[704/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[705/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[706/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[707/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[708/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[709/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[710/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[711/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[712/1343] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[713/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_app_desc.c.obj +[714/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/debug.c.obj +[715/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[716/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[717/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[718/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_startup.c.obj +[719/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition_target.c.obj +[720/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_trace.c.obj +[721/1343] Building C object esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj +[722/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_reader.c.obj +[723/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition.c.obj +[724/1343] Linking C static library esp-idf/esp_system/libesp_system.a +[725/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cache.c.obj +[726/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_ops.c.obj +[727/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_client.c.obj +[728/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_keys.c.obj +[729/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_server.c.obj +[730/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_generic.c.obj +[731/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_debug_helpers_generated.c.obj +[732/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ciphersuites.c.obj +[733/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cookie.c.obj +[734/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_client.c.obj +[735/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ticket.c.obj +[736/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_platform_time.c.obj +[737/1343] Linking C static library esp-idf/spi_flash/libspi_flash.a +[738/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/mbedtls_debug.c.obj +[739/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_client.c.obj +[740/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_msg.c.obj +[741/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/pkcs7.c.obj +[742/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_create.c.obj +[743/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/net_sockets.c.obj +[744/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crl.c.obj +[745/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_server.c.obj +[746/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write.c.obj +[747/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesni.c.obj +[748/1343] Linking C static library esp-idf/esp_mm/libesp_mm.a +[749/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_csr.c.obj +[750/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_csr.c.obj +[751/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_crt.c.obj +[752/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesce.c.obj +[753/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509.c.obj +[754/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aes.c.obj +[755/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod.c.obj +[756/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls.c.obj +[757/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod_raw.c.obj +[758/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/camellia.c.obj +[759/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1parse.c.obj +[760/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1write.c.obj +[761/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aria.c.obj +[762/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/block_cipher.c.obj +[763/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chacha20.c.obj +[764/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/base64.c.obj +[765/1343] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[766/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chachapoly.c.obj +[767/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crt.c.obj +[768/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ccm.c.obj +[769/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_core.c.obj +[770/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/des.c.obj +[771/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/dhm.c.obj +[772/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/constant_time.c.obj +[773/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecjpake.c.obj +[774/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher_wrap.c.obj +[775/1343] Linking C static library esp-idf/efuse/libefuse.a +[776/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdh.c.obj +[777/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves_new.c.obj +[778/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher.c.obj +[779/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cmac.c.obj +[780/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ctr_drbg.c.obj +[781/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdsa.c.obj +[782/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum.c.obj +[783/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy_poll.c.obj +[784/1343] Linking C static library esp-idf/esp_partition/libesp_partition.a +[785/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hkdf.c.obj +[786/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy.c.obj +[787/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/memory_buffer_alloc.c.obj +[788/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/nist_kw.c.obj +[789/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hmac_drbg.c.obj +[790/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md5.c.obj +[791/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lmots.c.obj +[792/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/error.c.obj +[793/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/padlock.c.obj +[794/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves.c.obj +[795/1343] Linking C static library esp-idf/app_update/libapp_update.a +[796/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lms.c.obj +[797/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/gcm.c.obj +[798/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md.c.obj +[799/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pem.c.obj +[800/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp.c.obj +[801/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_ecc.c.obj +[802/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/oid.c.obj +[803/1343] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[804/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/poly1305.c.obj +[805/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform.c.obj +[806/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk.c.obj +[807/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_wrap.c.obj +[808/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform_util.c.obj +[809/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs5.c.obj +[810/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs12.c.obj +[811/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkwrite.c.obj +[812/1343] Linking C static library esp-idf/esp_app_format/libesp_app_format.a +[813/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_aead.c.obj +[814/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_driver_wrappers_no_static.c.obj +[815/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_client.c.obj +[816/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_se.c.obj +[817/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkparse.c.obj +[818/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_cipher.c.obj +[819/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_pake.c.obj +[820/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ecp.c.obj +[821/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ffdh.c.obj +[822/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_hash.c.obj +[823/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ripemd160.c.obj +[824/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_rsa.c.obj +[825/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_mac.c.obj +[826/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_slot_management.c.obj +[827/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedtls.a +[828/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_storage.c.obj +[829/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_its_file.c.obj +[830/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha3.c.obj +[831/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha1.c.obj +[832/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/threading.c.obj +[833/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa_alt_helpers.c.obj +[834/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_util.c.obj +[835/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/timing.c.obj +[836/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha512.c.obj +[837/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha256.c.obj +[838/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version.c.obj +[839/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version_features.c.obj +[840/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_gdma_impl.c.obj +[841/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha_gdma_impl.c.obj +[842/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_mem.c.obj +[843/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hardware.c.obj +[844/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c.obj +[845/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_xts.c.obj +[846/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_common.c.obj +[847/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_dma_core.c.obj +[848/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_timing.c.obj +[849/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/esp_sha.c.obj +[850/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hmac_pbkdf2.c.obj +[851/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c.obj +[852/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/bignum_alt.c.obj +[853/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/sha.c.obj +[854/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_dec_alt.c.obj +[855/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c.obj +[856/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_ds_common.c.obj +[857/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/esp_bignum.c.obj +[858/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/md/esp_md.c.obj +[859/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa.c.obj +[860/1343] Creating directories for 'bootloader' +[861/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedx509.a +[862/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha1.c.obj +[863/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha256.c.obj +[864/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/x25519.c.obj +[865/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/Hacl_Curve25519_joined.c.obj +[866/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m_driver_entrypoints.c.obj +[867/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/everest.c.obj +[868/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m/p256-m.c.obj +[869/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha512.c.obj +[870/1343] No download step for 'bootloader' +[871/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_gcm.c.obj +[872/1343] No update step for 'bootloader' +[873/1343] No patch step for 'bootloader' +[874/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto.c.obj +[875/1343] Minifying + gzipping web resources +Minifying web resources in /tmp/tianshan-j1-build/build/esp-idf/ts_webui/web_optimized... + JS js/terminal.js: 31,064 -> 20,034 (35.5% saved) + JS js/router.js: 6,414 -> 3,839 (40.1% saved) + JS js/dragSort.js: 11,460 -> 7,603 (33.7% saved) + JS js/api.js: 36,638 -> 24,339 (33.6% saved) + JS js/i18n.js: 7,208 -> 4,320 (40.1% saved) + JS js/app.js: 1,129,944 -> 840,829 (25.6% saved) + JS js/lang/en-US.js: 178,439 -> 143,161 (19.8% saved) + JS js/lang/zh-CN.js: 172,046 -> 137,314 (20.2% saved) + CSS css/style.css: 179,071 -> 129,275 (27.8% saved) + CSS fonts/remixicon.css: 5,940 -> 4,860 (18.2% saved) + + Total saved: 442,650 bytes (432.3 KB) + +Gzipping web resources in /tmp/tianshan-j1-build/build/esp-idf/ts_webui/web_optimized... + GZ js/terminal.js: 20,034 -> 5,566 (72.2% smaller) + GZ js/router.js: 3,839 -> 1,340 (65.1% smaller) + GZ js/dragSort.js: 7,603 -> 1,869 (75.4% smaller) + GZ js/api.js: 24,339 -> 6,163 (74.7% smaller) + GZ js/i18n.js: 4,320 -> 1,460 (66.2% smaller) + GZ js/app.js: 840,829 -> 167,747 (80.0% smaller) + GZ js/lang/en-US.js: 143,161 -> 43,017 (70.0% smaller) + GZ js/lang/zh-CN.js: 137,314 -> 45,286 (67.0% smaller) + GZ css/style.css: 129,275 -> 20,658 (84.0% smaller) + GZ fonts/remixicon.css: 4,860 -> 1,263 (74.0% smaller) + GZ index.html: 26,685 -> 7,266 (72.8% smaller) + + Gzipped 11 files: 1,342,259 -> 301,635 (77.5% overall) +Done. +[876/1343] cd /tmp/tianshan-j1-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-j1-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-j1-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[877/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a +[878/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/p256-m/libp256m.a +[879/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/everest/libeverest.a +[880/1343] Generating x509_crt_bundle +[881/1343] Generating ../../x509_crt_bundle.S +[882/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_context.S.obj +[883/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr_asm.S.obj +[884/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[885/1343] Building ASM object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/__/__/x509_crt_bundle.S.obj +[886/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[887/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_trace.c.obj +[888/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_glitch_filter_ops.c.obj +[889/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj +[890/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_vectors.S.obj +[891/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr.c.obj +[892/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_pin_glitch_filter.c.obj +[893/1343] Building C object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/esp_crt_bundle/esp_crt_bundle.c.obj +[894/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/Partition.cpp.obj +[895/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj +[896/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/crc32.cpp.obj +[897/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/SPI_Flash.cpp.obj +[898/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/rtc_io.c.obj +[899/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Perf.cpp.obj +[900/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/dedic_gpio.c.obj +[901/1343] Linking C static library esp-idf/mbedtls/libmbedtls.a +[902/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Safe.cpp.obj +[903/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/wear_levelling.cpp.obj +[904/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio.c.obj +[905/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_rawflash.c.obj +[906/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_wl.c.obj +[907/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/port/freertos/ffsystem.c.obj +[908/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_sdmmc.c.obj +[909/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ffunicode.c.obj +[910/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio.c.obj +[911/1343] Linking C static library esp-idf/esp_pm/libesp_pm.a +[912/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_spiflash.c.obj +[913/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_cache.c.obj +[914/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs_api.c.obj +[915/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_sdmmc.c.obj +[916/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Flash.cpp.obj +[917/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_gc.c.obj +[918/1343] Linking C static library esp-idf/esp_driver_gpio/libesp_driver_gpio.a +[919/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_check.c.obj +[920/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/split_argv.c.obj +[921/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_hydrogen.c.obj +[922/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_common.c.obj +[923/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/esp_spiffs.c.obj +[924/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat.c.obj +[925/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/commands.c.obj +[926/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_cmd.c.obj +[927/1343] Linking C static library esp-idf/xtensa/libxtensa.a +[928/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_internal.c.obj +[929/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_chip.c.obj +[930/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dbl.c.obj +[931/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_date.c.obj +[932/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dstr.c.obj +[933/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_end.c.obj +[934/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_file.c.obj +[935/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/linenoise/linenoise.c.obj +[936/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rem.c.obj +[937/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_hashtable.c.obj +[938/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_int.c.obj +[939/1343] Linking C static library esp-idf/wear_levelling/libwear_levelling.a +[940/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_lit.c.obj +[941/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_str.c.obj +[942/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_nucleus.c.obj +[943/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_utils.c.obj +[944/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ff.c.obj +[945/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rex.c.obj +[946/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/compress.c.obj +[947/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth_netif_glue.c.obj +[948/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/argtable3.c.obj +[949/1343] Linking C static library esp-idf/spiffs/libspiffs.a +[950/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/adler32.c.obj +[951/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/crc32.c.obj +[952/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_phy_w5500.c.obj +[953/1343] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON_Utils.c.obj +[954/1343] Linking C static library esp-idf/fatfs/libfatfs.a +[955/1343] Building C object esp-idf/ts_event/CMakeFiles/__idf_ts_event.dir/src/ts_event.c.obj +[956/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth.c.obj +[957/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/phy/esp_eth_phy_802_3.c.obj +[958/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzclose.c.obj +[959/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzlib.c.obj +[960/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzread.c.obj +[961/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzwrite.c.obj +[962/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_mac_w5500.c.obj +[963/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inftrees.c.obj +[964/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/uncompr.c.obj +[965/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inffast.c.obj +[966/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/infback.c.obj +[967/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/zutil.c.obj +[968/1343] Linking C static library esp-idf/ts_event/libts_event.a +[969/1343] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON.c.obj +[970/1343] Linking C static library esp-idf/console/libconsole.a +[971/1343] Linking C static library esp-idf/esp_eth/libesp_eth.a +[972/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/deflate.c.obj +[973/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/example.c.obj +[974/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/trees.c.obj +[975/1343] Building C object esp-idf/ts_log/CMakeFiles/__idf_ts_log.dir/src/ts_log.c.obj +[976/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_encoder.c.obj +[977/1343] Linking C static library esp-idf/json/libjson.a +[978/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_dev.c.obj +[979/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_api.c.obj +[980/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inflate.c.obj +[981/1343] Building C object esp-idf/espressif__esp_jpeg/CMakeFiles/__idf_espressif__esp_jpeg.dir/jpeg_decoder.c.obj +[982/1343] Building C object esp-idf/esp_https_server/CMakeFiles/__idf_esp_https_server.dir/src/https_server.c.obj +[983/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_spi_dev.c.obj +[984/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngmem.c.obj +[985/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngerror.c.obj +[986/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrio.c.obj +[987/1343] Linking C static library esp-idf/espressif__zlib/libespressif__zlib.a +[988/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngpread.c.obj +[989/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwio.c.obj +[990/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngget.c.obj +[991/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtrans.c.obj +[992/1343] Building C object esp-idf/espressif__esp_websocket_client/CMakeFiles/__idf_espressif__esp_websocket_client.dir/esp_websocket_client.c.obj +[993/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtest.c.obj +[994/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/png.c.obj +[995/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwtran.c.obj +[996/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngset.c.obj +[997/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_mem_caps.c.obj +[998/1343] Building C object esp-idf/ts_jsonpath/CMakeFiles/__idf_ts_jsonpath.dir/src/ts_jsonpath.c.obj +[999/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngread.c.obj +[1000/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_networking_lwip.c.obj +[1001/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwrite.c.obj +[1002/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/blowfish.c.obj +[1003/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwutil.c.obj +[1004/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent.c.obj +[1005/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrutil.c.obj +[1006/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent_win.c.obj +[1007/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/bcrypt_pbkdf.c.obj +[1008/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_console.c.obj +[1009/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrtran.c.obj +[1010/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/comp.c.obj +[1011/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/crypt.c.obj +[1012/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/global.c.obj +[1013/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/channel.c.obj +[1014/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/libgcrypt.c.obj +[1015/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/keepalive.c.obj +[1016/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/hostkey.c.obj +[1017/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mac.c.obj +[1018/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/os400qc3.c.obj +[1019/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/openssl.c.obj +[1020/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/knownhost.c.obj +[1021/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/misc.c.obj +[1022/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mbedtls.c.obj +[1023/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/packet.c.obj +[1024/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/pem.c.obj +[1025/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/publickey.c.obj +[1026/1343] Linking C static library esp-idf/ts_log/libts_log.a +[1027/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth_kbd_packet.c.obj +[1028/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/version.c.obj +[1029/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/wincng.c.obj +[1030/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/scp.c.obj +[1031/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/session.c.obj +[1032/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/kex.c.obj +[1033/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/transport.c.obj +[1034/1343] Linking C static library esp-idf/esp_https_server/libesp_https_server.a +[1035/1343] Linking C static library esp-idf/espressif__esp_websocket_client/libespressif__esp_websocket_client.a +[1036/1343] Linking C static library esp-idf/espressif__led_strip/libespressif__led_strip.a +[1037/1343] Building C object esp-idf/ts_mempool/CMakeFiles/__idf_ts_mempool.dir/src/ts_mempool.c.obj +[1038/1343] Building C object esp-idf/ts_service/CMakeFiles/__idf_ts_service.dir/src/ts_service.c.obj +[1039/1343] Linking C static library esp-idf/espressif__esp_jpeg/libespressif__esp_jpeg.a +[1040/1343] Linking C static library esp-idf/ts_jsonpath/libts_jsonpath.a +[1041/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_json.c.obj +[1042/1343] Linking C static library esp-idf/espressif__libpng/libespressif__libpng.a +[1043/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_nvs.c.obj +[1044/1343] Linking C static library esp-idf/ts_mempool/libts_mempool.a +[1045/1343] Linking C static library esp-idf/ts_service/libts_service.a +[1046/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth.c.obj +[1047/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_schemas.c.obj +[1048/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/sftp.c.obj +[1049/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config.c.obj +[1050/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_file.c.obj +[1051/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_meta.c.obj +[1052/1343] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert_time.c.obj +[1053/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns.c.obj +[1054/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_security.c.obj +[1055/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_auth.c.obj +[1056/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_module.c.obj +[1057/1343] Linking C static library esp-idf/ch405labs_esp_libssh2/libch405labs_esp_libssh2.a +[1058/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_client.c.obj +[1059/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_scp.c.obj +[1060/1343] Linking C static library esp-idf/espressif__mdns/libespressif__mdns.a +[1061/1343] Building C object esp-idf/ts_config_pack/CMakeFiles/__idf_ts_config_pack.dir/src/ts_config_pack.c.obj +[1062/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_sftp.c.obj +[1063/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_crypto.c.obj +[1064/1343] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert.c.obj +[1065/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_probe.c.obj +[1066/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_known_hosts.c.obj +[1067/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_shell.c.obj +[1068/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_port_forward.c.obj +[1069/1343] Linking C static library esp-idf/ts_config/libts_config.a +[1070/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_log_watch.c.obj +[1071/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_keystore.c.obj +[1072/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_hosts_config.c.obj +[1073/1343] Linking C static library esp-idf/ts_config_pack/libts_config_pack.a +[1074/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_compat.c.obj +[1075/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_variable.c.obj +[1076/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_automation.c.obj +[1077/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_codec.c.obj +[1078/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_store.c.obj +[1079/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_service.c.obj +[1080/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_runner.c.obj +[1081/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_freertos.c.obj +[1082/1343] Linking C static library esp-idf/ts_cert/libts_cert.a +[1083/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_commands_config.c.obj +[1084/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_cache.c.obj +[1085/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_memory.c.obj +[1086/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/port/esp/unity_utils_memory_esp.c.obj +[1087/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/constants.pb-c.c.obj +[1088/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_port_esp32.c.obj +[1089/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec0.pb-c.c.obj +[1090/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec1.pb-c.c.obj +[1091/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity/src/unity.c.obj +[1092/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/session.pb-c.c.obj +[1093/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec2.pb-c.c.obj +[1094/1343] Linking C static library esp-idf/ts_security/libts_security.a +[1095/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/common/protocomm.c.obj +[1096/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security0.c.obj +[1097/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_console.c.obj +[1098/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp_mpi.c.obj +[1099/1343] Building C object esp-idf/protobuf-c/CMakeFiles/__idf_protobuf-c.dir/protobuf-c/protobuf-c/protobuf-c.c.obj +[1100/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_httpd.c.obj +[1101/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_engine.c.obj +[1102/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/host_file_io.c.obj +[1103/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp.c.obj +[1104/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace_util.c.obj +[1105/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/port/port_uart.c.obj +[1106/1343] Linking C static library esp-idf/unity/libunity.a +[1107/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace.c.obj +[1108/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security1.c.obj +[1109/1343] Building C object esp-idf/cmock/CMakeFiles/__idf_cmock.dir/CMock/src/cmock.c.obj +[1110/1343] Linking C static library esp-idf/protobuf-c/libprotobuf-c.a +[1111/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security2.c.obj +[1112/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/esp_cam_ctlr.c.obj +[1113/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_source_manager.c.obj +[1114/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp_share_ctrl.c.obj +[1115/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_gdma.c.obj +[1116/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_action_manager.c.obj +[1117/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidd.c.obj +[1118/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hid_common.c.obj +[1119/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_common.c.obj +[1120/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidh.c.obj +[1121/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_io.c.obj +[1122/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ops.c.obj +[1123/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ssd1306.c.obj +[1124/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_nt35510.c.obj +[1125/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_st7789.c.obj +[1126/1343] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/common/touch_sens_common.c.obj +[1127/1343] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/hw_ver2/touch_version_specific.c.obj +[1128/1343] Linking C static library esp-idf/ts_automation/libts_automation.a +[1129/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v1.c.obj +[1130/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_cam.c.obj +[1131/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v2.c.obj +[1132/1343] Generating ../../lpmu-agx-network-setup.tar.gz.S +[1133/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_init.c.obj +[1134/1343] Linking C static library esp-idf/protocomm/libprotocomm.a +[1135/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/spi/esp_lcd_panel_io_spi.c.obj +[1136/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/proto-c/esp_local_ctrl.pb-c.c.obj +[1137/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_common.c.obj +[1138/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_transport_httpd.c.obj +[1139/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_uart.c.obj +[1140/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_elf.c.obj +[1141/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_binary.c.obj +[1142/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_handler.c.obj +[1143/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_flash.c.obj +[1144/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl.c.obj +[1145/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api.c.obj +[1146/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config.c.obj +[1147/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i80/esp_lcd_panel_io_i80.c.obj +[1148/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_power.c.obj +[1149/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_system.c.obj +[1150/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_service.c.obj +[1151/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config_pack.c.obj +[1152/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_gpio.c.obj +[1153/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_fan.c.obj +[1154/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_network.c.obj +[1155/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_temp.c.obj +[1156/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_monitor.c.obj +[1157/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_storage.c.obj +[1158/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_dhcp.c.obj +[1159/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_device.c.obj +[1160/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_wifi.c.obj +[1161/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_nat.c.obj +[1162/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_led.c.obj +[1163/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/rgb/esp_lcd_panel_rgb.c.obj +[1164/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_hosts.c.obj +[1165/1343] Building ASM object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/__/__/lpmu-agx-network-setup.tar.gz.S.obj +[1166/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_key.c.obj +[1167/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_lpmu_access.c.obj +[1168/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_sftp.c.obj +[1169/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_auth.c.obj +[1170/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_log.c.obj +[1171/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_time.c.obj +[1172/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ui.c.obj +[1173/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_cert.c.obj +[1174/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui.c.obj +[1175/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_api.c.obj +[1176/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_auth.c.obj +[1177/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ota.c.obj +[1178/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https.c.obj +[1179/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_args.c.obj +[1180/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_api.c.obj +[1181/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_i18n.c.obj +[1182/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_builtin.c.obj +[1183/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_operation.c.obj +[1184/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console.c.obj +[1185/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ssh.c.obj +[1186/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_script.c.obj +[1187/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[1188/1343] Performing configure step for 'bootloader' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-j1-build/sdkconfig +-- Compiler supported targets: xtensa-esp-elf +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Bootloader project name: "bootloader" version: 1 +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.rom.ld +-- Components: bootloader bootloader_support efuse esp_app_format esp_bootloader_format esp_common esp_hw_support esp_rom esp_security esp_system esptool_py freertos hal log main micro-ecc newlib partition_table soc spi_flash xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/components/micro-ecc /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +-- Configuring done (3.3s) +-- Generating done (0.1s) +-- Build files have been written to: /tmp/tianshan-j1-build/build/bootloader +[1189/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_transport.c.obj +[1190/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_auto.c.obj +[1191/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_monitor.c.obj +[1192/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_device.c.obj +[1193/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/linenoise/linenoise.c.obj +[1194/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fan.c.obj +[1195/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_config.c.obj +[1196/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_gpio.c.obj +[1197/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fs.c.obj +[1198/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_dhcp.c.obj +[1199/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[1200/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_hosts.c.obj +[1201/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_nat.c.obj +[1202/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_register.c.obj +[1203/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_key.c.obj +[1204/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_net.c.obj +[1205/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ota.c.obj +[1206/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_power.c.obj +[1207/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_pki.c.obj +[1208/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_service.c.obj +[1209/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_storage.c.obj +[1210/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_sftp.c.obj +[1211/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_voltprot.c.obj +[1212/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota.c.obj +[1213/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_temp.c.obj +[1214/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_rollback.c.obj +[1215/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_version.c.obj +[1216/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_wifi.c.obj +[1217/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_automation.c.obj +[1218/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_system.c.obj +[1219/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_led.c.obj +[1220/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_sdcard.c.obj +[1221/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_https.c.obj +[1222/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_recovery.c.obj +[1223/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ssh.c.obj +[1224/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net.c.obj +[1225/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_wifi.c.obj +[1226/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_eth.c.obj +[1227/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_www.c.obj +[1228/1343] Linking C static library esp-idf/ts_api/libts_api.a +[1229/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net_manager.c.obj +[1230/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_nat.c.obj +[1231/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led.c.obj +[1232/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_driver.c.obj +[1233/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_http_server.c.obj +[1234/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_layer.c.obj +[1235/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_time_sync.c.obj +[1236/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color.c.obj +[1237/1343] Linking C static library esp-idf/ts_https/libts_https.a +[1238/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_https_server.c.obj +[1239/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_download.c.obj +[1240/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_qrcode.c.obj +[1241/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_dhcp_server.c.obj +[1242/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_animation.c.obj +[1243/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_drivers.c.obj +[1244/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color_correction.c.obj +[1245/1343] Linking C static library esp-idf/ts_webui/libts_webui.a +[1246/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_font.c.obj +[1247/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_effect.c.obj +[1248/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_usb_mux.c.obj +[1249/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power.c.obj +[1250/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_preset.c.obj +[1251/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/qrcodegen/qrcodegen.c.obj +[1252/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_text.c.obj +[1253/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_monitor.c.obj +[1254/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_fan.c.obj +[1255/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_hal.c.obj +[1256/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_image.c.obj +[1257/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_device_ctrl.c.obj +[1258/1343] Linking C static library esp-idf/ts_console/libts_console.a +[1259/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_policy.c.obj +[1260/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_gpio.c.obj +[1261/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_compute_monitor.c.obj +[1262/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_temp_source.c.obj +[1263/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/platform/esp32s3/ts_platform_s3.c.obj +[1264/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_i2c.c.obj +[1265/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_sha.c.obj +[1266/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_spi.c.obj +[1267/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pwm.c.obj +[1268/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_crc.c.obj +[1269/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_uart.c.obj +[1270/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_adc.c.obj +[1271/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_spiffs.c.obj +[1272/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pin_manager.c.obj +[1273/1343] Linking C static library esp-idf/ts_ota/libts_ota.a +[1274/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage.c.obj +[1275/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/port/xtensa/core_dump_port.c.obj +[1276/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_access.c.obj +[1277/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_masks.c.obj +[1278/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_sd.c.obj +[1279/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_apis.c.obj +[1280/1343] Building C object esp-idf/nvs_sec_provider/CMakeFiles/__idf_nvs_sec_provider.dir/nvs_sec_provider.c.obj +[1281/1343] Linking C static library esp-idf/ts_net/libts_net.a +[1282/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/platform_esp32_idf.c.obj +[1283/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_outbox.c.obj +[1284/1343] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_utils.c.obj +[1285/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_msg.c.obj +[1286/1343] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_mqueue.c.obj +[1287/1343] Building C object esp-idf/ts_pki_client/CMakeFiles/__idf_ts_pki_client.dir/src/ts_pki_client.c.obj +[1288/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_private.c.obj +[1289/1343] Linking C static library esp-idf/ts_led/libts_led.a +[1290/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_helpers.c.obj +[1291/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_button.c.obj +[1292/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_matrix.c.obj +[1293/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_slider.c.obj +[1294/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hub.c.obj +[1295/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_element.c.obj +[1296/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_config.c.obj +[1297/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/enum.c.obj +[1298/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_ctrl.c.obj +[1299/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_phy.c.obj +[1300/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_scan.c.obj +[1301/1343] Linking C static library esp-idf/ts_drivers/libts_drivers.a +[1302/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usbh.c.obj +[1303/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_console.c.obj +[1304/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_ctrl.pb-c.c.obj +[1305/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_scan.pb-c.c.obj +[1306/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_constants.pb-c.c.obj +[1307/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/handlers.c.obj +[1308/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_host.c.obj +[1309/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_config.pb-c.c.obj +[1310/1343] Linking C static library esp-idf/ts_hal/libts_hal.a +[1311/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_softap.c.obj +[1312/1343] Linking C static library esp-idf/app_trace/libapp_trace.a +[1313/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hcd_dwc.c.obj +[1314/1343] Linking C static library esp-idf/cmock/libcmock.a +[1315/1343] Linking C static library esp-idf/esp_driver_cam/libesp_driver_cam.a +[1316/1343] Linking C static library esp-idf/esp_driver_touch_sens/libesp_driver_touch_sens.a +[1317/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/main.c.obj +[1318/1343] Linking C static library esp-idf/esp_hid/libesp_hid.a +[1319/1343] Linking C static library esp-idf/esp_local_ctrl/libesp_local_ctrl.a +[1320/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_core_init.c.obj +[1321/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/mqtt_client.c.obj +[1322/1343] Linking C static library esp-idf/esp_lcd/libesp_lcd.a +[1323/1343] Linking C static library esp-idf/espcoredump/libespcoredump.a +[1324/1343] Linking C static library esp-idf/ts_storage/libts_storage.a +[1325/1343] Linking C static library esp-idf/nvs_sec_provider/libnvs_sec_provider.a +[1326/1343] Linking C static library esp-idf/perfmon/libperfmon.a +[1327/1343] Linking C static library esp-idf/rt/librt.a +[1328/1343] Linking C static library esp-idf/touch_element/libtouch_element.a +[1329/1343] Linking C static library esp-idf/usb/libusb.a +[1330/1343] Linking C static library esp-idf/mqtt/libmqtt.a +[1331/1343] Linking C static library esp-idf/ts_pki_client/libts_pki_client.a +[1332/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/manager.c.obj +[1333/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_services.c.obj +[1334/1343] Linking C static library esp-idf/wifi_provisioning/libwifi_provisioning.a +[1335/1343] Linking C static library esp-idf/main/libmain.a +[1336/1343] Performing build step for 'bootloader' +[1/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_timestamp.c.obj +[2/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/util.c.obj +[3/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[4/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[5/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_lock.c.obj +[6/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[7/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[8/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[9/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[10/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[11/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[12/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[13/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[14/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[15/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[16/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[17/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[18/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[19/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[20/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[21/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[22/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[23/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[24/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[25/123] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[26/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[27/123] Linking C static library esp-idf/log/liblog.a +[28/123] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[29/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[30/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[31/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[32/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[33/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[34/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[35/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[36/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[37/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[38/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[39/123] Linking C static library esp-idf/esp_rom/libesp_rom.a +[40/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[41/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[42/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[43/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[44/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[45/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[46/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[47/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[48/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[49/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[50/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[51/123] Linking C static library esp-idf/esp_common/libesp_common.a +[52/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[53/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[54/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[55/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[56/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_loader.c.obj +[57/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[58/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[59/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console_loader.c.obj +[60/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_soc.c.obj +[61/123] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[62/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[63/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console.c.obj +[64/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_panic.c.obj +[65/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[66/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_esp32s3.c.obj +[67/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_init.c.obj +[68/123] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[69/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[70/123] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[71/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[72/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[73/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[74/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[75/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[76/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[77/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[78/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[79/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[80/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[81/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[82/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[83/123] Linking C static library esp-idf/esp_system/libesp_system.a +[84/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[85/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[86/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[87/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[88/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[89/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[90/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[91/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[92/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[93/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[94/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[95/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[96/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[97/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[98/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[99/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[100/123] Generating project_elf_src_esp32s3.c +[101/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[102/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[103/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[104/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[105/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[106/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[107/123] Linking C static library esp-idf/efuse/libefuse.a +[108/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[109/123] Building C object CMakeFiles/bootloader.elf.dir/project_elf_src_esp32s3.c.obj +[110/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[111/123] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/bootloader_start.c.obj +[112/123] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[113/123] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[114/123] Linking C static library esp-idf/spi_flash/libspi_flash.a +[115/123] Building C object esp-idf/micro-ecc/CMakeFiles/__idf_micro-ecc.dir/uECC_verify_antifault.c.obj +[116/123] Linking C static library esp-idf/hal/libhal.a +[117/123] Linking C static library esp-idf/micro-ecc/libmicro-ecc.a +[118/123] Linking C static library esp-idf/soc/libsoc.a +[119/123] Linking C static library esp-idf/xtensa/libxtensa.a +[120/123] Linking C static library esp-idf/main/libmain.a +[121/123] Linking C executable bootloader.elf +[122/123] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-j1-build/build/bootloader/bootloader.bin +[123/123] cd /tmp/tianshan-j1-build/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-j1-build/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[1337/1343] No install step for 'bootloader' +[1338/1343] Completed 'bootloader' +[1339/1343] Generating esp-idf/esp_system/ld/sections.ld +[1340/1343] Building C object CMakeFiles/TianShanOS.elf.dir/project_elf_src_esp32s3.c.obj +[1341/1343] Linking CXX executable TianShanOS.elf +[1342/1343] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-j1-build/build/TianShanOS.bin +[1343/1343] cd /tmp/tianshan-j1-build/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-j1-build/build/partition_table/partition-table.bin /tmp/tianshan-j1-build/build/TianShanOS.bin +TianShanOS.bin binary size 0x215120 bytes. Smallest app partition is 0x300000 bytes. 0xeaee0 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-j1-build/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-j1-build/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-j1-build/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-j1-build/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-j1-build/build/www.bin +or from the "/private/tmp/tianshan-j1-build/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ws-j1/changes.patch b/docs/repair/ws-j1/changes.patch new file mode 100644 index 0000000..20b26c7 --- /dev/null +++ b/docs/repair/ws-j1/changes.patch @@ -0,0 +1,195 @@ +diff --git a/components/ts_webui/web/index.html b/components/ts_webui/web/index.html +index d4aa9c9..59265c7 100644 +--- a/components/ts_webui/web/index.html ++++ b/components/ts_webui/web/index.html +@@ -41,9 +41,9 @@ + .modal-content{background:var(--bg-card);border-radius:var(--radius-lg);max-width:600px;width:95%;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg)} + + +- +- +- ++ ++ ++ + + + +@@ -247,7 +247,7 @@ + + + +- +- +- +- +- ++ ++ ++ ++ ++ + + +diff --git a/components/ts_webui/web/js/terminal.js b/components/ts_webui/web/js/terminal.js +index ccd3a51..8fb1240 100644 +--- a/components/ts_webui/web/js/terminal.js ++++ b/components/ts_webui/web/js/terminal.js +@@ -477,6 +477,7 @@ class WebTerminal { + * 处理电压保护事件 + */ + handlePowerEvent(msg) { ++ if (this.destroyed || !this.terminal) return; + const state = msg.state || 'UNKNOWN'; + const voltage = msg.voltage ? msg.voltage.toFixed(2) : '?.??'; + const countdown = msg.countdown || 0; +@@ -535,6 +536,19 @@ class WebTerminal { + } + + if (notification) { ++ const canRestoreLocalInput = ++ !this.destroyed && ++ this.connected && ++ this.ws && ++ this.ws.readyState === WebSocket.OPEN && ++ !this.sshMode && ++ !this.sshConnecting && ++ !this.sshDisconnecting && ++ !this.restoring; ++ if (!canRestoreLocalInput) { ++ this.writeln(`\r\n${color}${notification}\x1b[0m`); ++ return; ++ } + // 保存当前输入状态 + const savedBuffer = this.inputBuffer; + const savedPosition = this.cursorPosition; +diff --git a/tests/prompts/project-cross.cjs b/tests/prompts/project-cross.cjs +index c902f24..acc03de 100644 +--- a/tests/prompts/project-cross.cjs ++++ b/tests/prompts/project-cross.cjs +@@ -48,6 +48,22 @@ async function main(){ + if(baseline){assert(!recovered && next.type!=='ssh_input');await step({cmd:'finish'});await done;assert.equal(exit,0,err);console.log('CONFIRMED H1: actual C request error leaves op OPEN but JS exits SSH and next input is not routed to SSH');return;} + assert(recovered,'request failure changed active SSH mode/prompt/recovery');assert.equal(next.type,'ssh_input'); + let cs=await step({message:next});assert.equal(cs.writes,afterSignal.writes+1,'next frontend input must execute on original C Shell'); ++ // J1: real C protection notification must not fabricate local SSH input. ++ const j1Before=await state(),j1Frames=records.length,j1Identity=cs.identity,j1Writes=cs.writes; ++ await e.run(`term.inputBuffer='local-buffer';term.cursorPosition=3;`); ++ const j1Fields=()=>e.run(`JSON.stringify([term.connected,term.sshMode,term.sshConnecting,term.sshDisconnecting,term.restoring,term.inputBuffer,term.cursorPosition])`); ++ const j1Snapshot=await j1Fields();cs=await step({cmd:'power'}); ++ const j1After=await state(),j1Display=j1After.lines.slice(j1Before.lines.length); ++ assert(records.slice(j1Frames).some(r=>r.fd===1&&r.frame?.type==='power_event'),'actual C power frame absent'); ++ assert.equal(j1Display.length,1);assert(j1Display[0].startsWith('\r\n')); ++ assert(!j1Display.join('').includes('tianshan>')&&!j1Display.join('').includes('local-buffer')&&!j1Display.join('').includes('\x1b[K')); ++ assert.equal(await j1Fields(),j1Snapshot);assert.deepEqual(j1After.sent,j1Before.sent); ++ await e.run(`input('j')`);const j1Request=await e.run('sent.shift()');assert.equal(j1Request.type,'ssh_input'); ++ cs=await step({message:j1Request});assert.equal(cs.identity,j1Identity);assert.equal(cs.writes,j1Writes+1); ++ await e.run(`input('\\x1c')`);await sendNext();assert(!(await state()).mode);assert.equal((await step({cmd:'drain'})).channels,0); ++ assert((await state()).lines.slice(j1Before.lines.length).includes('tianshan> ')); ++ await e.run(`term.inputBuffer='';term.cursorPosition=0;`);cs=await start();assert((await state()).mode); ++ console.log('PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup'); + for(const message of [{type:'ssh_resize',width:0,height:20},{type:'ssh_resize',width:80.5,height:20}]){await step({message});assert((await state()).mode);} + await step({cmd:'resize_reject'});await step({message:{type:'ssh_resize',width:80,height:24}});assert((await state()).mode);await step({cmd:'reset_driver'}); + // Another page cannot input, disconnect, signal or resize the current owner. +diff --git a/tests/prompts/regression.test.cjs b/tests/prompts/regression.test.cjs +index d6bf002..2d9db10 100644 +--- a/tests/prompts/regression.test.cjs ++++ b/tests/prompts/regression.test.cjs +@@ -169,3 +169,40 @@ for(const lang of ['zh-CN','en-US']) { + } + }); + } ++ ++for (const lang of ['zh-CN','en-US']) { ++ test(`${lang}: J1 power alerts preserve local line, SSH ownership, transition guards and filtering`,async()=>{ ++ const h=await setup(lang),{run,ctx}=h; ++ run(`window.j1=new WebTerminal('fixture');window.j1Writes=[];window.j1Sent=[];window.j1Input=null; ++ j1.terminal={write:s=>j1Writes.push(s),writeln:s=>j1Writes.push(s),onData:f=>j1Input=f}; ++ j1.ws={readyState:WebSocket.OPEN,send:s=>j1Sent.push(JSON.parse(s))};j1.connected=true; ++ j1.inputBuffer='abcd';j1.cursorPosition=2;j1.setupInputHandler();`); ++ const alert={type:'power_event',event:'low_voltage',voltage:10.5}; ++ const snapshot=()=>run(`JSON.stringify([j1.connected,j1.sshMode,j1.sshConnecting,j1.sshDisconnecting,j1.restoring,j1.inputBuffer,j1.cursorPosition])`); ++ const deliver=msg=>ctx.j1.handleMessage(msg||alert); ++ const original=snapshot();deliver();deliver();assert.equal(snapshot(),original);assert.equal(ctx.j1Sent.length,0); ++ const local=[...ctx.j1Writes];assert.equal(local.length,8); ++ for(const offset of [0,4]){assert.equal(local[offset],'\r\x1b[K');assert(local[offset+1].includes(ctx.t('terminal.lowVoltageWarning',{voltage:'10.50'})));assert.equal(local[offset+2],'tianshan> abcd');assert.equal(local[offset+3],'\x1b[2D');} ++ const cases=[{sshMode:true},{sshConnecting:true},{sshMode:true,sshDisconnecting:true},{restoring:true,connected:false},{restoring:true},{connected:false},{socket:3},{socket:null}]; ++ for(const changes of cases){ ++ run(`Object.assign(j1,{connected:true,sshMode:false,sshConnecting:false,sshDisconnecting:false,restoring:false});j1.ws={readyState:1,send:s=>j1Sent.push(JSON.parse(s))};j1Writes.length=0;`); ++ for(const [key,value]of Object.entries(changes)){if(key==='socket'){if(value===null)ctx.j1.ws=null;else ctx.j1.ws.readyState=value;}else ctx.j1[key]=value;} ++ const before=snapshot();deliver();deliver();assert.equal(snapshot(),before);assert.equal(ctx.j1Sent.length,0); ++ assert.equal(ctx.j1Writes.length,2);for(const line of ctx.j1Writes){assert(line.startsWith('\r\n'));assert(!line.includes('tianshan>'));assert(!line.includes('abcd'));assert(!line.includes('\x1b[K'));assert(!line.includes('\x1b[2D'));} ++ if(changes.sshConnecting||changes.sshDisconnecting||changes.connected===false){run('j1Input('+JSON.stringify('x\r')+')');assert.equal(ctx.j1Sent.length,0);} ++ } ++ run(`Object.assign(j1,{connected:true,sshMode:true,sshConnecting:false,sshDisconnecting:false,restoring:false});j1.ws={readyState:1,send:s=>j1Sent.push(JSON.parse(s))};j1Writes.length=0;`); ++ deliver();run(`j1Input('z')`);assert.equal(ctx.j1Sent[0].type,'ssh_input');assert.equal(ctx.j1Sent[0].data,'z'); ++ run(`j1Input('\x1c')`);assert.equal(ctx.j1Sent[1].type,'ssh_disconnect');assert(ctx.j1.sshMode);assert(!ctx.j1Writes.join('').includes('tianshan>')); ++ deliver({type:'ssh_status',status:'disconnecting'});deliver();assert(ctx.j1.sshMode);assert(!ctx.j1Writes.join('').includes('tianshan>')); ++ deliver({type:'ssh_status',status:'closed'});assert(!ctx.j1.sshMode);assert.equal(ctx.j1Writes.filter(x=>x==='tianshan> ').length,1); ++ ctx.j1Writes.length=0;deliver();assert.equal(ctx.j1Writes[2],'tianshan> abcd');assert.equal(ctx.j1Writes[3],'\x1b[2D');assert.equal(ctx.j1Sent.length,2); ++ ctx.j1Writes.length=0;deliver({type:'power_event',event:'countdown_tick',countdown:31});assert.equal(ctx.j1Writes.length,0); ++ for(const event of ['low_voltage','shutdown_start','protected','recovery_start','recovery_complete','debug_tick','state_changed','countdown_tick']){ ++ ctx.j1Writes.length=0;deliver({type:'power_event',event,countdown:30,voltage:10.5,state:'NORMAL'});assert.equal(ctx.j1Writes.length,4,event); ++ } ++ ctx.j1.destroyed=true;ctx.j1.terminal=new Proxy({}, {get(){throw Error('destroyed terminal accessed');}}); ++ assert.doesNotThrow(()=>ctx.j1.handlePowerEvent(alert));assert.doesNotThrow(()=>deliver()); ++ ctx.j1.destroyed=false;ctx.j1.terminal=null;assert.doesNotThrow(()=>ctx.j1.handlePowerEvent(alert));assert.equal(ctx.j1Sent.length,2); ++ }); ++} +diff --git a/tests/ws_subscriptions/test_project.c b/tests/ws_subscriptions/test_project.c +index b7b63f7..3966f69 100644 +--- a/tests/ws_subscriptions/test_project.c ++++ b/tests/ws_subscriptions/test_project.c +@@ -13,6 +13,11 @@ int main(void){ + cJSON *j=cJSON_Parse(line);assert(j);const char *cmd=cJSON_GetStringValue(cJSON_GetObjectItem(j,"cmd")); + if(cmd && !strcmp(cmd,"finish")){ssh_cleanup();if(shell_task.fn){shell_task.fn(shell_task.arg);shell_task.fn=NULL;}drive_all();cJSON_Delete(j);finish_all();assert(!driver_channels&&!driver_sessions&&!driver_sockets);puts("{\"finished\":true}");return 0;} + if(cmd && !strcmp(cmd,"eof")){driver_eof=true;shell_task.fn(shell_task.arg);shell_task.fn=NULL;drive_all();} ++ else if(cmd && !strcmp(cmd,"power")){ ++ ts_power_policy_status_t status={.state=TS_POWER_POLICY_STATE_LOW_VOLTAGE,.current_voltage=10.5f,.countdown_remaining_sec=30}; ++ ts_event_t event={.id=TS_POWER_POLICY_EVENT_LOW_VOLTAGE,.data=&status}; ++ power_policy_event_handler(&event,NULL);drive_all(); ++ } + else if(cmd && !strcmp(cmd,"output")){ssh_shell_context_t *ctx=shell_task.arg;ssh_send_output(ctx,"stream",6);} + else if(cmd && !strcmp(cmd,"error_close")){barrier_name="request_error_encode";barrier_action=close_during_error;} + else if(cmd && !strcmp(cmd,"write_again"))driver_write_again=true; +@@ -34,7 +39,7 @@ int main(void){ + } + if(shell_task.fn && (((ssh_shell_context_t*)shell_task.arg)->disconnect_requested || !ts_ws_op_is_open(((ssh_shell_context_t*)shell_task.arg)->op))){shell_task.fn(shell_task.arg);shell_task.fn=NULL;drive_all();} + ts_ws_op_stats_t st;ts_ws_op_stats(TS_WS_OP_SHELL,&st); +- printf("{\"state\":%d,\"writes\":%d,\"live\":%u,\"channels\":%d,\"refs\":%u,\"preparing\":%u,\"unsettled\":%u}\n",st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j); ++ printf("{\"identity\":%u,\"state\":%d,\"writes\":%d,\"live\":%u,\"channels\":%d,\"refs\":%u,\"preparing\":%u,\"unsettled\":%u}\n",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j); + } + return 2; + } +diff --git a/tests/ws_subscriptions/verify_project_assets.py b/tests/ws_subscriptions/verify_project_assets.py +index 20e4116..bbcda8b 100644 +--- a/tests/ws_subscriptions/verify_project_assets.py ++++ b/tests/ws_subscriptions/verify_project_assets.py +@@ -1,15 +1,16 @@ + #!/usr/bin/env python3 + """Verify final optimized/gzip files and reproduce SPIFFS with the fixed SDK.""" +-import gzip,hashlib,json,os,pathlib,subprocess,tempfile ++import gzip,hashlib,json,os,pathlib,re,subprocess,tempfile + root=pathlib.Path(__file__).resolve().parents[2] +-build=pathlib.Path(os.environ.get('V3_BUILD','/tmp/tianshan-project-v3-build/build'));web=build/'esp-idf/ts_webui/web_optimized';src=root/'components/ts_webui/web';doc=root/'docs/repair/ws-project-v3' ++build=pathlib.Path(os.environ.get('V3_BUILD','/tmp/tianshan-project-v3-build/build'));web=build/'esp-idf/ts_webui/web_optimized';src=root/'components/ts_webui/web';doc=pathlib.Path(os.environ.get('V3_RESULTS',str(root/'docs/repair/ws-project-v3'))) + sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest() + result={} + for rel in ['index.html','js/terminal.js','js/lang/zh-CN.js','js/lang/en-US.js']: + p=web/rel;gz=p.with_suffix(p.suffix+'.gz');assert gzip.decompress(gz.read_bytes())==p.read_bytes() + if rel.endswith('.js'):subprocess.run(['node','--check',str(p)],check=True) + result[rel]={'source_sha256':sha(src/rel),'optimized_sha256':sha(p),'gzip_sha256':sha(gz),'optimized_bytes':p.stat().st_size} +-assert '20260926-shell-contract' in (web/'index.html').read_text() ++asset_version=re.search(r"TS_ASSET_VERSION = '([^']+)'",(src/'index.html').read_text()).group(1) ++assert asset_version in (web/'index.html').read_text() + assert 'sshControlUnsupported' in (web/'js/terminal.js').read_text() + with tempfile.TemporaryDirectory(prefix='ts-v3-spiffs-') as d: + image=pathlib.Path(d)/'www.bin' diff --git a/docs/repair/ws-j1/cross-browser-en-US.json b/docs/repair/ws-j1/cross-browser-en-US.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ws-j1/cross-browser-en-US.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-j1/cross-browser-en-US.txt b/docs/repair/ws-j1/cross-browser-en-US.txt new file mode 100644 index 0000000..f832b4b --- /dev/null +++ b/docs/repair/ws-j1/cross-browser-en-US.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/cross-browser-zh-CN.json b/docs/repair/ws-j1/cross-browser-zh-CN.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ws-j1/cross-browser-zh-CN.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-j1/cross-browser-zh-CN.txt b/docs/repair/ws-j1/cross-browser-zh-CN.txt new file mode 100644 index 0000000..1f8c8bd --- /dev/null +++ b/docs/repair/ws-j1/cross-browser-zh-CN.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/cross-node-en-US.json b/docs/repair/ws-j1/cross-node-en-US.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ws-j1/cross-node-en-US.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-j1/cross-node-en-US.txt b/docs/repair/ws-j1/cross-node-en-US.txt new file mode 100644 index 0000000..7c3e1b4 --- /dev/null +++ b/docs/repair/ws-j1/cross-node-en-US.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/cross-node-results.json b/docs/repair/ws-j1/cross-node-results.json new file mode 100644 index 0000000..5cf1c51 --- /dev/null +++ b/docs/repair/ws-j1/cross-node-results.json @@ -0,0 +1,18 @@ +[ + { + "language": "zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs" + ], + "exit": 0 + }, + { + "language": "en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ws-j1/cross-node-zh-CN.json b/docs/repair/ws-j1/cross-node-zh-CN.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ws-j1/cross-node-zh-CN.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-j1/cross-node-zh-CN.txt b/docs/repair/ws-j1/cross-node-zh-CN.txt new file mode 100644 index 0000000..4699bd2 --- /dev/null +++ b/docs/repair/ws-j1/cross-node-zh-CN.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/diff-check.txt b/docs/repair/ws-j1/diff-check.txt new file mode 100644 index 0000000..7ef22e9 --- /dev/null +++ b/docs/repair/ws-j1/diff-check.txt @@ -0,0 +1 @@ +PASS diff --git a/docs/repair/ws-j1/inputs.json b/docs/repair/ws-j1/inputs.json new file mode 100644 index 0000000..dda219d --- /dev/null +++ b/docs/repair/ws-j1/inputs.json @@ -0,0 +1,31 @@ +{ + "head": "8ad39a9b1ca39d225f94fb4db602fb2ee7438d09", + "branch": "fix/v0.5.2-reliability-and-prompts", + "sha256": { + "components/ts_webui/web/index.html": { + "before": "cb1baa1bfbd2fac00a5fc55caa5442da07ab83b99996af52a41fc5c7e6e98092", + "after": "ad6e0ed5e11c34b8797877be912ea2e42a5dc632b6cdae1b915222ea6ea6315b" + }, + "components/ts_webui/web/js/terminal.js": { + "before": "6d93870c3b33b1888388f3a288cfca581a3034a2a212e1e4130853d1aceda581", + "after": "8bfa9622f6fafb8cf1c88ab1081b47fa32df0fdd1814acdf67bd7708326ec0a1" + }, + "tests/prompts/project-cross.cjs": { + "before": "7928610e031f5e0b6ad001f14f0dd5ac39f534dfea253108747f433ae5e92a76", + "after": "882a05fea9b75a9d3b959e4e7c1e44db8b89289faaa5837ab9e1779959e6a70c" + }, + "tests/prompts/regression.test.cjs": { + "before": "c372b74e125b361103defe66017c3eeb286fea9975cf4f3167ed5cf981050516", + "after": "40ced30bd90f4e7c8529ef0ccb3c89af573796a4feff7a0531095c0cf60ff82c" + }, + "tests/ws_subscriptions/test_project.c": { + "before": "c8026c5105688edfe0e06e502bddcd7e44fcafb2def960bec53d773b6135e675", + "after": "071fd81304d303ecb4c3679952ba9da648c088447aa47cf6bde120830f890d46" + }, + "tests/ws_subscriptions/verify_project_assets.py": { + "before": "0ed7406a6927115f4574187158e53bd085d6cf3afc2962254c62133c839c9c43", + "after": "555cded164a2d1f8d096b1071e06c63928c121bb05be6d44fe8da7522d0b2e6b" + } + }, + "scope": "terminal.js outside handlePowerEvent unchanged; index only cache key; no production backend changes" +} \ No newline at end of file diff --git a/docs/repair/ws-j1/optimized-cross-en-US.json b/docs/repair/ws-j1/optimized-cross-en-US.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ws-j1/optimized-cross-en-US.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-j1/optimized-cross-en-US.txt b/docs/repair/ws-j1/optimized-cross-en-US.txt new file mode 100644 index 0000000..f832b4b --- /dev/null +++ b/docs/repair/ws-j1/optimized-cross-en-US.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/optimized-cross-zh-CN.json b/docs/repair/ws-j1/optimized-cross-zh-CN.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/ws-j1/optimized-cross-zh-CN.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-j1/optimized-cross-zh-CN.txt b/docs/repair/ws-j1/optimized-cross-zh-CN.txt new file mode 100644 index 0000000..1f8c8bd --- /dev/null +++ b/docs/repair/ws-j1/optimized-cross-zh-CN.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Chrome zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/optimized-results.json b/docs/repair/ws-j1/optimized-results.json new file mode 100644 index 0000000..b9b1232 --- /dev/null +++ b/docs/repair/ws-j1/optimized-results.json @@ -0,0 +1,20 @@ +[ + { + "language": "zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + }, + { + "language": "en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ws-j1/publication-cross.txt b/docs/repair/ws-j1/publication-cross.txt new file mode 100644 index 0000000..7c3e1b4 --- /dev/null +++ b/docs/repair/ws-j1/publication-cross.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-j1/publication-gate.md b/docs/repair/ws-j1/publication-gate.md new file mode 100644 index 0000000..b41d7c0 --- /dev/null +++ b/docs/repair/ws-j1/publication-gate.md @@ -0,0 +1,21 @@ +# J1 提交前审查 + +结论:可以推送。用户已另行授权更新 PR #42,不授权合并或发布。 + +基线:8ad39a9b1ca39d225f94fb4db602fb2ee7438d09;远端 PR 仍为 OPEN,head 与本地基线相同。 + +## 范围与不变量 + +检查完整六文件 diff:生产代码仅 handlePowerEvent 与静态资源缓存标识;测试夹具调用真实保护通知、socket 消费、输入回调与 C handler。无生产后端、协议、版本或工作流修改。原事件筛选及本地行恢复保留;非本地可交互状态只显示通知,不改变状态或输入目的地。原跨层断言保留。 + +## 本次补跑 + +- `node --test --test-name-pattern=J1 tests/prompts/regression.test.cjs`:通过,见 publication-node.txt。 +- `IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf DEVELOPER_DIR=/Library/Developer/CommandLineTools node tests/prompts/project-cross.cjs`:通过,见 publication-cross.txt。实际 C 告警经过生产 JS 后,下一输入仍进入原 SSH,正常退出并回收。 +- `git diff --check`:通过。六项当前源码/测试 SHA256 与 inputs.json 的 after 值全部一致。 + +本次发布准备未重复完整浏览器套件或固件编译,采用本轮 J1 实施阶段相同输入的 WebUI、双语跨层、优化资源 Chrome、固定 SDK 独立目录编译及 SPIFFS 一致性证据,详见 README。历史 v3 结果单独保留,不代替 J1 验证。 + +## 提交与验收边界 + +只纳入六个 J1 源码/测试文件及本目录。output/、tmp/ 与 runtime-repair 下原未跟踪文件排除,保持原样。没有发现本轮范围内阻断提交的问题;这不代表整个 PR 无缺陷。真实设备电源告警、SSH/xterm 呈现、网络时序及设备缓存升级仍需实机验收,未操作设备。 diff --git a/docs/repair/ws-j1/publication-node.txt b/docs/repair/ws-j1/publication-node.txt new file mode 100644 index 0000000..9e7652a --- /dev/null +++ b/docs/repair/ws-j1/publication-node.txt @@ -0,0 +1,10 @@ +✔ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (16.265167ms) +✔ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (5.204708ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 65.025875 diff --git a/docs/repair/ws-j1/webui-browser.txt b/docs/repair/ws-j1/webui-browser.txt new file mode 100644 index 0000000..d3c5a1b --- /dev/null +++ b/docs/repair/ws-j1/webui-browser.txt @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (4806.164125ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (261.186833ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (323.698667ms) +✔ en-US: initial language failure blocks controls and retry recovers (340.39075ms) +✔ delayed language package and rapid switches keep the latest requested language (285.129ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (374.057667ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (301.959959ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (321.459375ms) +✔ initial delayed language keeps controls inert until the real package arrives (232.756458ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (392.509917ms) +✔ terminal can initialize after failed resource load using newly served resources (385.423459ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (4732.002584ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (192.381708ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (179.46875ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (250.126042ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (283.28325ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (248.24125ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (174.608875ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (180.996333ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (163.60775ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (192.989417ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (190.113083ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (195.161459ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (273.16925ms) +✔ R3: late validation cannot revive an old apply entry en-US (245.426625ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (241.695959ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (242.689959ms) +✔ R6: fixed upload destination and separate refresh failure en-US (228.44125ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (237.10725ms) +✔ R2: authenticated startup initializes once (261.73075ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (239.543791ms) +✔ R4/R5: newest result wins over late success and late failure (224.590792ms) +✔ R3: overlapping writes to one path cannot claim current verified content (232.761625ms) +✔ R2: disposed page only removes its dashboard callback (261.315459ms) +✔ R2: stale finally cannot unlock the new page read (233.281167ms) +✔ R1: delayed sign-out does not clear a newer sign-in (230.918292ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (298.276333ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (359.741125ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 11145.844209 diff --git a/docs/repair/ws-j1/webui-node.txt b/docs/repair/ws-j1/webui-node.txt new file mode 100644 index 0000000..311e552 --- /dev/null +++ b/docs/repair/ws-j1/webui-node.txt @@ -0,0 +1,53 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (15.437209ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.145792ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (7.544167ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (4.853291ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (4.952125ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (4.974875ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (5.576125ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (6.079542ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.603083ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.138ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.974209ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.478917ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.4665ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.078791ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (5.453791ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.370333ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.022792ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.485083ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.825875ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.332125ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.430666ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (8.141375ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.413375ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (4.351666ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.789459ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.308583ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (4.797458ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (5.053458ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.387166ms) +✔ en-US: upload and download aggregates cover all success and all failure (4.694167ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (4.379459ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.56425ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.548542ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.390541ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.448583ms) +✔ en-US: unknown stop result never escalates to forced termination (4.318833ms) +✔ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (4.955875ms) +✔ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (5.157542ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.812667ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.128375ms) +ℹ tests 40 +ℹ suites 0 +ℹ pass 40 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 256.997333 diff --git a/docs/repair/ws-operation/README.md b/docs/repair/ws-operation/README.md new file mode 100644 index 0000000..3f74925 --- /dev/null +++ b/docs/repair/ws-operation/README.md @@ -0,0 +1,120 @@ +# PR #42:Shell / Exec 生命周期统一修复(实现与验证记录) + +本轮修改前基线为 `74b1b646ec4a45f9159bd028e622b13fca5eff75`,分支 `fix/v0.5.2-reliability-and-prompts`。本轮已完成代码迁移;G1/G2 在完整冻结生产编译单元中复现,当前完整生产路径通过对应行为断言。**这是本地证据,不是设备验收或发布许可。** + +实现与验证阶段未提交、推送或更新 PR;随后用户另行授权将本轮代码和证据提交至 Fork 并更新 PR #42,见 `publication-gate.md`。本轮没有改变版本或发布流程,也没有连接设备、刷机、重启或执行远端命令。原有 `output/`、`tmp/`、未跟踪的 reviewer diff-check 文件保留。 + +## 1. 基线与实际反例 + +- `baseline.tar.gz`、`baseline.json`:开始修改前的生产源码、原测试、HEAD、分支、状态和逐文件 SHA256。 +- `public-headers.json`:反例编译所用且与基线相同的真实业务头文件哈希。 +- `design.md`:编码前形成的调用图、状态、所有权和迁移底稿。 +- `baseline-g1-g2.txt`:完整冻结 WS / manager / TX 编译单元的反例日志;只插入调度暂停点,不替换状态声明或清理函数。 + +**G1 的可达调度**:poller 提交输出后已返回;发送 worker 稍后向 SDK 入队失败;失败回调减掉输出计数后暂停。HTTPD 关闭原连接,真实 `ssh_cleanup` 等待独立 poller 退出;旧目标已失效,旧终态同步拒绝并结算。随后 HTTPD 重连并创建新 Shell。旧 worker 回调恢复后误用新全局状态,把新会话关闭。冻结源码断言 `replacement_corrupted=1`。 + +**G2 的可达调度**:输出 A 等待 SDK 提交,生产者开始编码 B。B 通过旧 stream_publish 的失败检查后暂停;worker 处理 A 的真实入队失败,真实 output_done 封口并发出 error。B 随后仍提交成功,观察到终态之后又出现 output。冻结源码断言 `terminal_before_late_output=1`。 + +本轮早期的隔离夹具用于定位;最终证据已替换成上述完整编译单元、真实声明及清理路径。G1 不依赖把同一 poller 的同步调用人为当成两个并发任务。反例脚本只把编译成功后的业务断言失败视为红灯。冻结旧 Exec 另有凭据字符串泄漏,反例夹具在真实 task cleanup **之后**释放这些独立字符串,仅用于恢复测试分配账本,不代替生命周期逻辑。当前统一析构已正确释放这些原操作拥有的字符串。 + +## 2. 唯一状态来源与并发决定点 + +新增内部 `ts_ws_operation.c/.h`,固定 Shell、Exec 各一个槽,没有新增任务或扩展会话并发。 + +| 状态 | 准入和退出条件 | +|---|---| +| FREE | 无资源和活引用;create 与停止创建门在同一个 `s_op_lock` 内排序 | +| STARTING | 创建租约已占槽,保留终态实际内存及描述符;资源准备失败走 discard | +| OPEN | 允许取输出票据;Shell 必须成功发送同步 connected 后才开放;Exec 只表示观察准入,start 消息仍在 SSH 连接成功后发送 | +| CLOSING | 同锁关闭准入;首个关闭者持 builder 引用冻结接收者、准备结果;先前失败可以补入最终事实 | +| FINALIZING | builder 完成、preparing=0、unsettled=0 后唯一认领;移动并清空槽内 reservation 别名 | +| TERMINAL_PENDING | 终态文本已封存;整批目标先登记,再逐目标提交;finalizer 引用保留到全部 submit 返回 | +| TERMINAL_SETTLED | 每个终态目标已有本地结算;不代表浏览器确认收到,也不代表业务执行者结束 | +| RECLAIMING | refs=0 且所有执行、准备、投递责任配平;拒绝 acquire/create,锁外析构,再标 FREE | + +决定点均在 `s_op_lock`:create/stop、acquire、output_begin、close_locked、整批 target 注册/单次结算、finalizer 认领、RECLAIMING。锁内只处理固定大小状态及计数,不执行 JSON、分配、网络或等待;没有和 TX 锁嵌套。 + +票据在复制观察输出、JSON 编码、payload 分配前取得,携带原操作、序号、原目标快照及准备责任。票据持续到整批交接返回。失败回调把“失败事实、关门、目标计数变化”放在同一个锁内,保留原操作引用到回调最后一次访问之后。重复/旧 token 不重复减计数,也不会作用于替换操作。 + +普通观察消息的生产者保持单一:Shell poller;Exec executor(start/output/match)。用户 disconnect 请求交给原 Shell poller 顺序发 `disconnecting` 再关闭,保留原有消息类型和字段。connecting/connected 是 HTTPD 同步控制路径,由创建引用和 STARTING 阶段保护;poller 在 OPEN 前不能输出,停止 barrier 必须等 handler 返回。 + +## 3. 所有权与完整迁移 + +| 资源/责任 | 原 owner 与释放点 | +|---|---| +| 创建租约 | create 在分配前占槽;task-create 前增加独立 executor 引用;创建者直到返回前都保留自己的引用,允许 task 早于 create 返回执行完 | +| Shell 资源 | task arg 的 `ssh_shell_context_t`;poller/失败创建者关闭 session/shell;输入、resize、signal 借用原操作,和清理共用资源 mutex;最后析构仅释放 context/mutex | +| Exec 参数、凭据、输出缓存 | task arg 的 `ssh_exec_task_params_t`;输出回调拿原 params 并借用原 op;业务结束关闭 session,最终析构释放参数、字符串、缓存、mutex | +| 输出准备票据 | begin 增 preparing/ref;无目标不编码;全部交接或失败后统一 finish,不能中途漏还 | +| 输出/终态投递 | 固定 token 记录;接受后由 TX done 结算,拒绝由发布者结算;早回调时 ticket/finalizer 仍保活;不重播整个多目标批次 | +| 关闭 builder | 首个 close 独占;Exec 在此冻结全局有效接收者,Shell 固定原 peer;之后加入者不追补旧终态 | +| 终态预留 | 每个原操作创建时取得;finalizer move 一次;封存后不修改文本;无目标、拒绝、SDK 重试耗尽和实际发送失败都释放 | +| Exec timer | timer ID 为原 params;创建到 timer daemon 排空 barrier 完成期间额外持引用;不把 delete 命令入队当成回调退出 | + +删除了旧 `s_ssh_state/generation/running/poll_alive/result_pending/output_pending/terminal_ready` 和 Exec 的 current params/session、creators、pending、claimed/result_active 等竞争状态。会话身份统一由原操作 ID 给出,跨服务重启不复用;32 位公开 ID 耗尽后拒绝新创建,不回绕制造 ABA。 + +`ssh_send_output`、Exec output 的真实上游编码、started/match、错误/完成、cancel、连接失效、输入/resize/signal、cleanup、创建失败和停止均已迁移。业务模式匹配、变量更新、底层 SSH deadline/abort 规则未改;观察输出失败只封闭 Exec 网页观察,后续业务仍正常收集和匹配,不自动重放或额外取消远端命令。 + +额外补齐同一不变量所需的错误处理:真实创建错误码向上传递;JSON 任一必要字段构造失败使用完整 fallback,不发送半个协议对象;失败的 task-create 释放自己的 executor 责任;cancel(0) 仍按原契约拒绝。 + +## 4. 推进与停止 + +现有 subscription worker 的 `run_batch` 调用 `ts_ws_op_poll`,负责封口、回收及 timer 排空;没有另起线程、事件队列或无限保留消息。 + +停止顺序:关闭创建门 → 暂停遥测 → HTTPD handler barrier → 请求原 Shell 退出 → Exec 业务仍执行则返回 busy;其他原操作在最多 2 秒的协作窗口排空 → 同步注销并排空保护事件、退出日志回调 → manager drain → TX drain → worker 退出。 + +任何 busy/timeout/error 都保留后续所需依赖;worker/HTTPD/event 回调自停被拒绝。健康 Shell 能在同次停止中排空,慢发送或旧 timer 仍占用时保留状态供重试。上层 HTTP / WebUI / service / core 的错误传播不需再改,已运行其真实函数回归。 + +Timer delete 和 daemon barrier 每个阶段最多 300 次失败入队尝试,失败间隔至少 100 ms;成功的 delete 不再重发,只重试尚未接受的 barrier。耗尽后记录错误并保留原引用,停止重试显式恢复同一阶段。SDK 接受 barrier 后若 daemon 永久不运行,不能安全推断回调已退出:保持 busy/timeout 与有界占用,不伪造回收。临时队列拥塞在恢复后无新业务消息也能自行推进。 + +SDK 依据:固定 v5.5.2 的 `FreeRTOS-Kernel/timers.c::prvProcessReceivedCommands` 在同一 daemon 顺序执行 DELETE 和 pended function。原 Exec 仍使用 SSH 驱动自身 deadline;本轮未改变额外 timer 分配/启动失败时的业务策略,测试确认其引用可正确退出。当前 sdkconfig 启用 `CONFIG_STDATOMIC_S32C1I_SPIRAM_WORKAROUND=y`;已核查 SDK newlib 外部 RAM 原子操作路径及目标编译代码,没有假定原生 CAS 能访问 PSRAM。 + +## 5. 验证与证据边界 + +下列均为本轮实际执行;日志在同目录。主机 C 使用真实 SDK cJSON、ASan/UBSan,SDK/网络/时钟由可控边界替身提供。 + +| 命令(先设置 IDF_PATH) | 结果 / 日志 | +|---|---| +| `python3 tests/ws_subscriptions/replay_operation_baseline.py` | 确认 G1/G2 真实旧行为失败,`baseline-g1-g2.txt` | +| `bash tests/ws_subscriptions/run_operation.sh` | 生产控制层+TX:36 个屏障调度、16 个编码/SDK/socket/stale 组合及重复 token 账本,`operation-tests.txt` | +| `bash tests/ws_subscriptions/run_operation_adapter.sh` | **整个生产 WS 编译单元**、实际声明、创建/任务/回调/cleanup/stop,`adapter-tests.txt` | +| `bash tests/ws_subscriptions/run_host.sh` | 遥测、TX、事件节点保活/排空、HTTP/WebUI、初始化失败,`host-tests.txt` | +| `bash tests/ws_subscriptions/run_reviewer.sh` | R1/R4 停止、R3 角色、R5 公平性及上层依赖,`reviewer-tests.txt`;Shell R2 的创建失败/早关闭在完整 adapter 入口保留 | +| `bash tests/ws_subscriptions/run_f1_f2.sh` | F1/F2、分配/描述符/字节容量、分类、部分失败、连续业务、停止、公平性,`f1-f2-tests.txt` | +| `bash tests/ws_subscriptions/run_f1_f2.sh --baseline` | 历史 F1/F2 红灯仍可复现;使用匹配旧 ABI 的冻结夹具,`historical-f1-f2.txt` | +| `bash tests/runtime/run_all.sh` | 当前运行时回归,`runtime-tests.txt` | +| `bash tests/certificate/run_host.sh` | 当前证书/HTTPS 回归,`certificate-tests.txt`;其中 REPRODUCED 为套件固定旧版反例 | +| `npm --prefix tests/prompts test` | 38 项 Node 检查,`webui-node-tests.txt` | +| `npm --prefix tests/prompts run test:browser` | 中英文 Chrome 38 项,后端模拟,`webui-browser-tests.txt` | +| `idf.py -B /tmp/tianshan-op-build/build -D SDKCONFIG=/tmp/tianshan-op-build/sdkconfig build` | ESP-IDF v5.5.2 / ESP32-S3 独立目录编译、链接成功,`build.txt`、`build-artifacts.json` | +| `git diff --check` | 通过,`diff-check.txt` | + +B01—B10 覆盖取得引用/票据、准备与注册、SDK 回调早于 submit 返回、失败回调尚未退出、关闭构造暂停、终态部分交接、业务仍运行、回收前拒绝复用;B11 使用真实停止和现有 worker 验证无新消息推进。新增 adapter 场景还覆盖:旧连接失效重连、终态快照后新增连接、用户 disconnect 消息、cancel ID、timer 排空/超限重试/早 barrier、真实匹配和变量更新、16 个创建分配位置及 48 个输出编码分配位置。 + +账本断言为 `tickets=finished+preparing`、`registered=settled+unsettled`、finalizer 至多一次、重复 token 不重复结算、FREE 无活引用/资源;结合 TX 原有 accepted/settled 与分配计数检查泄漏和双重释放。不是用测试数量代替行为证明。 + +旧 reviewer/F1/F2 测试已迁移到完整 WS 编译单元,保留有效行为断言。初始化故障注入仍是单独的 initializer 测试,不再用简化 cleanup/global 夹具证明新的会话协议。没有修改 CI 工作流;后续可在提供 IDF_PATH 的主机 job 接入上述两个新 operation 入口。 + +首次构建被沙箱的系统进程查询限制阻挡、首次 Chrome 启动被沙箱阻挡;获工具批准后完成本地重跑。没有将启动失败当作业务反例。没有运行 TSan:当前 SDK 替身的全局可控调度不是任意并发线程模型。屏障枚举不等于穷尽 ESP32 双核调度。 + +## 6. 资源预算(目标编译器测量) + +详见 `resources.txt`,目标工具链的 sizeof、nm 和 `-fstack-usage`,不是主机指针尺寸估算。 + +- 两个固定操作槽各 **928 B**,共 **1856 B**;控制锁/序号/标志另 26 B。移除旧 Shell/Exec 全局 630 B,相关静态净增 **1252 B**(不含链接对齐)。 +- 每槽固定 16 个普通输出 token、8 个终态 token,每 token 16 B;它们是责任记录,**没有增加 TX 消息或描述符容量**。Shell 实际终态只有一个目标。 +- 栈上单个票据 **280 B**;Shell context 堆对象 20 B;Exec params 从 744 B 到 792 B。每种操作各一个资源 mutex(SDK 类型 92 B),同时活跃的额外业务堆开销约 **252 B**,不含分配器对齐。Exec params 仍优先 PSRAM。 +- Exec timer 对象 44 B,同时至多一个;从旧全局长期留存改为每代排空释放。daemon 使用既有队列,没有新任务或私有消息队列。 +- 传输预算仍为 15 个消息对象、96 个目标描述符、payload 总上限 1 MiB,其中保护独占 5 KiB;普通/遥测/结果/保护转换/周期分类不变。Shell 4 KiB、Exec 512 KiB 的终态容量仍在创建前预留。 +- 单函数目标栈帧:`ts_ws_op_poll` 576 B、`ts_ws_op_output_finish` 176 B、Shell output 320 B、Shell poller 2096 B、Exec output callback 1088 B、Exec task 560 B、run_batch 3360 B、power callback 736 B。**不是完整调用链峰值或实测水位**。原 worker 8192 B、Shell 4096 B、Exec 8192 B 配置未增加。 +- 当前应用 `0x214a50`,最小应用分区剩余 `0xeb5b0`(约 31%)。代码/固件 SHA256 记录用于识别本次产物,不证明设备运行效果。 + +U01/U02 对应原上下文与引用;U03/U04 对应 ticket/close 同锁;U05/U06 对应 preparing、目标和回调保活;U07/U08 对应 token 一次结算与原 TX 类别;U09/U10 对应终态封存及 executor 分离;U11 对应锁表;U12 对应真实 stop;U13 对应固定资源和 worker 推进;U14 对应当前 R1—R5/F1/F2、运行时、证书和双语回归。 + +## 7. 未执行及实机验收 + +没有发现本地证据中尚未关闭的 G1/G2;也不据此宣称无竞态。尚未执行:真实 SSH 服务/设备网络、ESP32 双核并发、慢浏览器/多标签连接、固件运行、堆水位和栈水位、真实 timer daemon 拥塞与完整 WebUI 服务重启。 + +需要另行授权实机验收:Shell 创建/输入/远端关闭/断开重连、Exec 正常/匹配/取消/超时及观察断线后业务继续;慢连接下普通输出与保护通知、遥测的公平性;发送/事件/timer 排空超时后的停止重试;多轮启停后的堆/句柄/任务和高水位。特别检查新增票据后的 Shell/Exec/worker 最低栈余量,以及 PSRAM 原子操作配置和真实调度表现。 + +本轮自查按完整调用链检查了旧字段残留、创建返回前 task 退出、回调计数归零后的引用、半成品 JSON、断开状态消息、cancel(0)、timer delete 的假排空、停止自等待及资源门限;发现的问题已修复并进入回归。不存在未经迁移保留的旧会话全局协议。前端布局、外部消息类型和字段、硬件保护以及 SSH 匹配规则保持原样。 diff --git a/docs/repair/ws-operation/adapter-tests.txt b/docs/repair/ws-operation/adapter-tests.txt new file mode 100644 index 0000000..7febc5e --- /dev/null +++ b/docs/repair/ws-operation/adapter-tests.txt @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=84 diff --git a/docs/repair/ws-operation/baseline-g1-g2.txt b/docs/repair/ws-operation/baseline-g1-g2.txt new file mode 100644 index 0000000..013fb9c --- /dev/null +++ b/docs/repair/ws-operation/baseline-g1-g2.txt @@ -0,0 +1,4 @@ +Frozen production source and original tests SHA256 verified +G1 complete production unit: replacement=2 old=1 replacement_corrupted=1 +G2 complete production unit: terminal_before_late_output=1 +CONFIRMED G1/G2 are business assertion failures in the complete frozen WS unit, not compile/dependency/cleanup failures diff --git a/docs/repair/ws-operation/baseline.json b/docs/repair/ws-operation/baseline.json new file mode 100644 index 0000000..ae92316 --- /dev/null +++ b/docs/repair/ws-operation/baseline.json @@ -0,0 +1,125 @@ +{ + "HEAD": "74b1b646ec4a45f9159bd028e622b13fca5eff75", + "branch": "fix/v0.5.2-reliability-and-prompts", + "sha256": { + "components/ts_core/CMakeLists.txt": "326c89b533f1a3a18f4a567695ef66aeca7ebe2b53ff9363ca466208e0e65905", + "components/ts_core/include/ts_core.h": "9504ead739f5011bfc7864103464bcd7d8c06eab2242d89391203164e9210197", + "components/ts_core/ts_config/CMakeLists.txt": "84e0791274bf45e4fa2c3373bfbb8f6ddcb2883c3dc7234a15fffd905a2dff9f", + "components/ts_core/ts_config/Kconfig": "7d319983a89dac10bd815eb94af1b0665a471e68709c6500ae298756161931c3", + "components/ts_core/ts_config/include/ts_config.h": "4945666dbcc7eb507f5a740061340a692e5add4ba3a4e5e421bd656d8b24b4ea", + "components/ts_core/ts_config/include/ts_config_file.h": "2d3bab9796164c3c2d945f2abd44e38dbdb37243283a62790275fe7872e65b78", + "components/ts_core/ts_config/include/ts_config_meta.h": "b649ab500111f98ba9035c525a625fc7ca21e0e553db1c978e03b35f24d43826", + "components/ts_core/ts_config/include/ts_config_module.h": "94873dac21ab86cc2f4eb4d7265588457e97e4386602773a3228c49b864bb472", + "components/ts_core/ts_config/include/ts_config_nvs.h": "2ec4ec9940dabd37df9de6f69d314583e1e77546c17fd67ccb5673a50be8a142", + "components/ts_core/ts_config/include/ts_config_schemas.h": "1b7de493a6e88d10155b558510e6ae4a72e31fbc1f77510c98b1ee8912ed94c1", + "components/ts_core/ts_config/src/ts_config.c": "c9a7b95660bfb29539cf323acd0ba66db8359a094347ea23740766a3b9721aaf", + "components/ts_core/ts_config/src/ts_config_file.c": "c61d01fec4b55560963a7995885c375f084dc54ee8ab52b47288eb68cd4403c0", + "components/ts_core/ts_config/src/ts_config_json.c": "be09570bcc58ef2dce1b4cce5968d2a0ce5a5ba0451295278ff16a66b7c32428", + "components/ts_core/ts_config/src/ts_config_meta.c": "ecf781cbcb200e56689bdaea34216cd033bf477eb1087eb1b03413334d2c92ec", + "components/ts_core/ts_config/src/ts_config_module.c": "f2c74dc811a31d4b5d0be2f2105f937ddddc5f52345763715e6fcaa6a74fbb8e", + "components/ts_core/ts_config/src/ts_config_nvs.c": "8dd95d5c09611a856e49770bc30ec971bd313cf759d833a6f97605f1dc6ef0c4", + "components/ts_core/ts_config/src/ts_config_schemas.c": "522aeba7427df30b89ab3ffb66b8637d3cf0c247af7133cdf2c04d45930994da", + "components/ts_core/ts_event/CMakeLists.txt": "c7f2d8ef1c3ac4e5bbfda512be49c5ade6acebf651ae8913e36e3f7e4ddd7506", + "components/ts_core/ts_event/Kconfig": "b1cf0bc9fa8ad38744b11d594a6f3aeb077a8ab88950c9695058e95aaea18929", + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_core/ts_jsonpath/src/ts_jsonpath.c": "115117f7a1281562ede7fe5666ba313cba8819742c8c22547a1ff0d0c9252c6f", + "components/ts_core/ts_log/CMakeLists.txt": "d149529554e03487f45cbf2f04d2989a996b328d94818614a91dfcba97c2697e", + "components/ts_core/ts_log/Kconfig": "35cb224534047beeb071dc83802e4c4532849b38d87e5feb75be5eea0634c972", + "components/ts_core/ts_log/include/ts_log.h": "beca44f4bde1ecba236f2a15d6a9bdd8037b3bb29f395e25b2f8ba4696847b57", + "components/ts_core/ts_log/src/ts_log.c": "c0cb7132cc80baa5ca03edb1adb13b0dfaa136bd4a0fd958307a43960be47b6c", + "components/ts_core/ts_log/src/ts_log_preview.h": "9e05ef9413323fc1ebe476e8fd73cf959767ceac9db7b4a5ddce17839e49b509", + "components/ts_core/ts_service/CMakeLists.txt": "ec3f90c75a8342547444c03165f61c9e9d5dfd1441598ede2aa93cf1711fac61", + "components/ts_core/ts_service/Kconfig": "3ab9397356f4485ed636b1af167714b75fc3d219386b8774ffe3bae6cfbd4675", + "components/ts_core/ts_service/include/ts_service.h": "2bbabd7738c2fb19880e45c0df169e3d5f6a226bbe1affdee030a7ddf8b2dd87", + "components/ts_core/ts_service/src/ts_service.c": "326b3ab1d4a61eba8b9bf43af26039fc4562092cbea19709764104278c79ec2b", + "components/ts_net/CMakeLists.txt": "d6aaac5a04b06bd536336820df0d5eb8c87e27b3087e5df41e640508314b163c", + "components/ts_net/Kconfig": "ddc14968f72310808d23b849248c7cb49411ed43e0f3c268060fb60da2f26e06", + "components/ts_net/include/ts_dhcp_server.h": "64e5e854f9b8fd7182f92dfafe594f3d8f1288ddecbbbec2c89b3aabee950c51", + "components/ts_net/include/ts_eth.h": "9f8952c77ade85741afb38aa48f3fb689a94164a2c598eb6c7df9344948cf8ce", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/include/ts_https_server.h": "f4c25017722b69f2f1bae48df34aa595f15d186ad3ec652b7be9d034e184bc79", + "components/ts_net/include/ts_nat.h": "1721b9c499ca0da09eb402d7db9211604a7a3414b6e2e7cf88169f872365a229", + "components/ts_net/include/ts_net.h": "2ddcd9233f0f5f63a83fdc6f3d09de3118b5b1cced5d9b009b3126c3b872a98b", + "components/ts_net/include/ts_net_manager.h": "6ad22613972f51af05eb6d468c04763808d92c1d6a6b0a7225911b24f9c0d9a5", + "components/ts_net/include/ts_time_sync.h": "e3ebf9da5b0c7b30a50a67fe07547e2c7fefd588474552579f4a2bc15ace8ca4", + "components/ts_net/include/ts_wifi.h": "25614f917387174bbbb7618010885353008e4488262303b314b87b78ae9f0905", + "components/ts_net/src/ts_dhcp_server.c": "800f32ac5097d4d73807496713a59488adfc417a1ea3be627a097cb4c9da0279", + "components/ts_net/src/ts_eth.c": "d2350045f8abe2d3bc1c046a51c5c0016b601f69bfe99ff2bfcdec8cf26e47fe", + "components/ts_net/src/ts_http_server.c": "0c8449fb396246074ef9deb404b2d5f98610f4f22f3c1ce70bf2774711dbb6ad", + "components/ts_net/src/ts_https_server.c": "50e9e0498aa7265739b99d9131eef726149fac255d20f152190d289df16b8ec9", + "components/ts_net/src/ts_nat.c": "e5accbee0cc4b7d0feccecc080b23726af94418f5f2c9645df785eb142a1eb24", + "components/ts_net/src/ts_net.c": "2f363e1c6cad3437449c742f42db70240cc34105942cfd2c2f3a854b226b8f92", + "components/ts_net/src/ts_net_manager.c": "4184c6e23f68b160a511fd8c44baa8133c04596fc00fcec459389ec61c14789f", + "components/ts_net/src/ts_time_sync.c": "d83f4591d1c45de7a89af7126c9921301a06ce2a6cb3890c5d302d491811db56", + "components/ts_net/src/ts_wifi.c": "54fdffed9cde1145b5dccc5e9419a72c94f83fbc395b225e76098be09b01ba3d", + "components/ts_webui/CMakeLists.txt": "9a52c046ca47d6e19fa001796ed7469387566e4cfb176a85d55a5f1b96f2fcfa", + "components/ts_webui/Kconfig": "6a1fc77d34f7c635b44a922f4c7c9fb96832a9f6bb433967c26e3bdc451ae286", + "components/ts_webui/include/ts_webui.h": "374e230b4f0d016adb2373acd2e6431cf537eaeb8f7f84efcf53523d6dad0402", + "components/ts_webui/include/ts_ws_subscriptions.h": "ab44ae214761c059ceebb993c61fa1ee8c0a8bc2b1a9b1bb19f864ea4dc534ea", + "components/ts_webui/include/ts_ws_transport.h": "dc7917b1d09c2569ce0d49f024f6a0db27924f81b1d58cdf0a7a7c51afeebdd6", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_api.c": "c8225f3fc36be3446947e205932a3d43340665d687b81c23c16556f3be8dc9b8", + "components/ts_webui/src/ts_webui_ws.c": "ea02c3ca56a37f8a4c850467c204246d774f80eb8386a970ab82a1ec24f8095c", + "components/ts_webui/src/ts_ws_subscriptions.c": "0782ccc9b76356d2a358e837a8f8cfa20f6aeb8f88b0f720d0ca0f037f4d5472", + "components/ts_webui/src/ts_ws_transport.c": "954540760b95964947bfbd3d2c5165aec8322c4e962ad48a806ff849475adabd", + "components/ts_webui/web/css/style.css": "30dab8799ed2a8b0a5da49ec84202b30f3c951779ea4533e847a53b2ac9b8dff", + "components/ts_webui/web/favicon.ico": "1ea04b690d7fe816da5efb405c13f9cd953366026eb3553e214de8d5df0d3648", + "components/ts_webui/web/fonts/remixicon.css": "b2218eec4e02513f0feef46f74f13c852152f54eafd83d1274057e3895f0ea1c", + "components/ts_webui/web/fonts/remixicon.woff2": "e92dc38bfb1d15dbb9d9ca9e645754f68e7c5b224e33c45a17048bd0cf2407a6", + "components/ts_webui/web/images/README.md": "f4429665c315cdabc2a935caf0f1423632dd7cbff84f34914965969217102237", + "components/ts_webui/web/images/favicon.icns": "bdc873fa7bff5e1888d80273f99f22d97d3719d4b17419e68e64eafd85c2b039", + "components/ts_webui/web/images/tslogo-128.png": "f09ac97789726872277a0399338cd9bfd0493752de930aeb6b2c6f7b0a864c3b", + "components/ts_webui/web/images/tslogo-256.png": "55dc7df59429c23fdc531baba002b7b23f5a4f2be0f29b2ecc5098f3df059da7", + "components/ts_webui/web/images/tslogo-32.png": "64e4bce72f2b13c81bef5b46ae919abeeb47f98571cf5e55460385880731810b", + "components/ts_webui/web/images/tslogo-48.png": "41f959e327dca63386a2f254b8a245a6fa151904a06eae93ae6c449277467f70", + "components/ts_webui/web/images/tslogo-512.png": "b7508585c46e16fcc7d42c52459ab55df32716aea85a10a560cd64de7cceb8e8", + "components/ts_webui/web/images/tslogo-64.png": "a0809405c5632eb4bf1f1b4783175c2b92b25fc522f5b0682a35d3cfa1c58752", + "components/ts_webui/web/images/tslogo-original.png": "9fb0ee8532c2d572d8b235f7586d225f00609cf8defb98b59cf55ae749e83ed1", + "components/ts_webui/web/index.html": "0b3ce77c7da2da7d18bd086dfe55fc33e994adbfe06f2f47eb6d69c01fe6124a", + "components/ts_webui/web/js/api.js": "6fb266abb3780a0d402d86ad95a3644b8e1f488136ad44dc18ddd83caaa8dab4", + "components/ts_webui/web/js/app.js": "ad63a38112eab45af87da091f3536156614db526bb85f2c83bafa7867439230b", + "components/ts_webui/web/js/dragSort.js": "7c5b9159cb8bb88b35222424db6d8bd822d3960899d5c090c17955700d6590af", + "components/ts_webui/web/js/i18n.js": "2eed1c54b4ef89bc2e4221a3fd900e88bd8d7a11064a04d97dcc3decfdeedbd8", + "components/ts_webui/web/js/lang/en-US.js": "70e02d67c772b659e5233356938c8344f1caf740ece2f6c3bbdc1c0a1e3c6f72", + "components/ts_webui/web/js/lang/zh-CN.js": "32ee2006259183f7ef03a98532e39a2a75b39c9ed9ab9680fa6279e90d9ea0af", + "components/ts_webui/web/js/router.js": "1e73ca3bf272a54aea8c516809e09e10f257b620bf66311bbbe358693fe377d5", + "components/ts_webui/web/js/terminal.js": "048ca0d64b9ee52b0c2b4f3f3f7e270a2bbd35fc729dbd513cc7b11dfb26bbcf", + "tests/ws_subscriptions/README.md": "e2a186d0cc38c5a2df86207cde9f371365b95e678908b15943a7556fe57e5ada", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/run_f1_f2.sh": "b07f3e0e40267a244515524f560b72276e8a23567ca96ec467787594cf4e4b3e", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/run_reviewer.sh": "17ea374c62bdbe2f8314423fe8538f864f0c9678405f13f1feb23e4ac22462d9", + "tests/ws_subscriptions/run_reviewer_baseline.sh": "6ea73543f64c6de65f59480300cf2d73ece85b798a7a430df5b55f2adae1bb96", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "de005401b26f9dce9028db4bbc656ea72e55730535769be4ddf31ccec072c2dc", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_f1_f2.c": "bda86a05b53a88441d653d0374d2d19b3d5ef24528e7b9f9577ae4bd4b03ce21", + "tests/ws_subscriptions/test_init.c": "c79aca85e117cb6fc34f3f493dc6d6d6083a0eb1488ba00abfcbeff903a96870", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/test_manager.c": "bc51e67c9c51c66780a8e980f5cbb93d7773fe5b9abce038d206f6d65ab0a23d", + "tests/ws_subscriptions/test_reviewer.c": "baedff8fca5d4ee62ccbf8d11dd4277d218b974ecacc9a6b55c2bf76f945653b", + "tests/ws_subscriptions/test_reviewer_core.c": "7669567ad82171ae32102779e4fc98c4b88871f9e9f761600a21623378882ef2", + "tests/ws_subscriptions/test_reviewer_http.c": "2b9696ac9dd86be96db383392d3bcf61f81a5ab2e881933d767aad8f91d30c00", + "tests/ws_subscriptions/test_reviewer_service.c": "3fa82db0882b90d69450ddcd7a50e5904ae60e2cab8e62ea11656ac4c21e2890", + "main/ts_core_init.c": "ad9b89b44eef49a72117197da3e2d44a0a9ba73cbf5d1a4c7c6a7e123ea41e1f" + }, + "initial_status": [ + "?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt", + "?? output/", + "?? tmp/" + ] +} diff --git a/docs/repair/ws-operation/baseline.tar.gz b/docs/repair/ws-operation/baseline.tar.gz new file mode 100644 index 0000000..1019179 Binary files /dev/null and b/docs/repair/ws-operation/baseline.tar.gz differ diff --git a/docs/repair/ws-operation/build-artifacts.json b/docs/repair/ws-operation/build-artifacts.json new file mode 100644 index 0000000..9a8ee73 --- /dev/null +++ b/docs/repair/ws-operation/build-artifacts.json @@ -0,0 +1,10 @@ +{ + "sdk": "ESP-IDF v5.5.2", + "target": "esp32s3", + "directory": "/tmp/tianshan-op-build/build", + "sha256": { + "/tmp/tianshan-op-build/build/TianShanOS.bin": "d131d46f4bfdf839bd1e8ea28a6b68b257563adc1726a7de28915f2a141daf6a", + "/tmp/tianshan-op-build/build/www.bin": "6c486bb7bc27d448cf0d9f351c98ab2d764e315fe82561122ccc4583391bfaad", + "/tmp/tianshan-op-build/sdkconfig": "1340e033b5865e39dd6b8c3516dffb27d01da5aff41127c69b583cbfb99acef0" + } +} diff --git a/docs/repair/ws-operation/build.txt b/docs/repair/ws-operation/build.txt new file mode 100644 index 0000000..68f7434 --- /dev/null +++ b/docs/repair/ws-operation/build.txt @@ -0,0 +1,33 @@ +Executing action: all (aliases: build) +Running ninja in directory /private/tmp/tianshan-op-build/build +Executing "ninja all"... +[1/13] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-op-build/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-op-build/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[2/13] No install step for 'bootloader' +[3/13] cd /tmp/tianshan-op-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-op-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-op-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[4/13] Completed 'bootloader' +[5/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_operation.c.obj +[6/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_api.c.obj +[7/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[8/13] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[9/13] Linking C static library esp-idf/ts_webui/libts_webui.a +[10/13] Generating esp-idf/esp_system/ld/sections.ld +[11/13] Linking CXX executable TianShanOS.elf +[12/13] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-op-build/build/TianShanOS.bin +[13/13] cd /tmp/tianshan-op-build/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-op-build/build/partition_table/partition-table.bin /tmp/tianshan-op-build/build/TianShanOS.bin +TianShanOS.bin binary size 0x214a50 bytes. Smallest app partition is 0x300000 bytes. 0xeb5b0 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-op-build/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-op-build/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-op-build/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-op-build/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-op-build/build/www.bin +or from the "/private/tmp/tianshan-op-build/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ws-operation/certificate-tests.txt b/docs/repair/ws-operation/certificate-tests.txt new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ws-operation/certificate-tests.txt @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ws-operation/changes.json b/docs/repair/ws-operation/changes.json new file mode 100644 index 0000000..9b05ac4 --- /dev/null +++ b/docs/repair/ws-operation/changes.json @@ -0,0 +1,29 @@ +{ + "HEAD": "74b1b646ec4a45f9159bd028e622b13fca5eff75", + "scope": "local only; no commit/push/PR/device operations", + "source_and_test_sha256": { + "components/ts_webui/CMakeLists.txt": "53e02258893758d55edf0debef2e0694b154ecccda65ab3b5bb5d34770c39d45", + "components/ts_webui/include/ts_ws_operation.h": "1c57f95fed42db3a478e73755c047b0ab64fe68b5dd3e64d0e6a7a673b6c8c11", + "components/ts_webui/include/ts_ws_subscriptions.h": "edcfedcdb48cc47bdd776218d43f362f4f2feb84f0a8bd347b465e3dd751e3ae", + "components/ts_webui/include/ts_ws_transport.h": "4c7b996ed4e6a578ce7daa1a02a13729795bd4dca2e66eb8b49895b6f59f36ee", + "components/ts_webui/src/ts_webui_ws.c": "ff9eb33748bf3c33a3df99273ec634512e74ca2207b610a8e4ee0791cdb56122", + "components/ts_webui/src/ts_ws_operation.c": "db6fa86b5759079e4477cdd9e1239bc1fc2d50c4b59cd007f9886638ce848097", + "components/ts_webui/src/ts_ws_subscriptions.c": "9f8d2f33a374d6992a1ef119cd20a791244e44abc8d7cd66dc906b4896f764fb", + "components/ts_webui/src/ts_ws_transport.c": "e2eaeb31d00d7996a84badc669ca5587628c63b044c9a8014e587e84b5ab37f8", + "tests/ws_subscriptions/baseline_operation_adapter.c": "0b0703b144fa8fc7d412110e55b4d7d2010196e9422deb78ff00185059a5af05", + "tests/ws_subscriptions/replay_operation_baseline.py": "ba26a739d9dfb4b30b4e10ac0b3955994738820b85a156406dcaaa9518382cc3", + "tests/ws_subscriptions/run_f1_f2.sh": "8e804b7a5c66663a62da53f9027b175722034e5cce77ba152aba8ad13b527935", + "tests/ws_subscriptions/run_operation.sh": "bf9d6db03b483d4b74db26e464efc73b673648ef82565edf987e6f275c9ee6c5", + "tests/ws_subscriptions/run_operation_adapter.sh": "1a5b900b4c6aae1619b86a285b6371a683263304db90a81d82477d8fb750d3f5", + "tests/ws_subscriptions/run_reviewer.sh": "2a957bb5d4e0ca0c357ec32fffb23aa60c75019b60cc4c5c33d468d389013ea8", + "tests/ws_subscriptions/stubs/esp_console.h": "f97fca9ebf2a497277d9ac5af3581a2e83789b4acf3e8b125e0f36fb27210151", + "tests/ws_subscriptions/stubs/freertos/timers.h": "fd6abec4a547b6e9caed8f0514a08ead4223303736dade89179bb8812a2a5d94", + "tests/ws_subscriptions/test_f1_f2.c": "7d4907e42f3a9c7110055acb6ca667abd62a5f16712306c7dde6b85ec285c9b4", + "tests/ws_subscriptions/test_init.c": "49b7ade237c4fe5df5fe683f4ec731c222cc4939b91b19d976471e99d29173c7", + "tests/ws_subscriptions/test_manager.c": "a1b46f3ad3a877a5cfd1235e7253418aec965c442a5c21ab811a68f1e70be8cd", + "tests/ws_subscriptions/test_operation.c": "c28fd00d191f92bbe8722033a3dbf5d7c6bcc54e054c06acff4429fce149a4e6", + "tests/ws_subscriptions/test_operation_adapter.c": "832ffe800b228b453d920e75e6d2070d0b45db6217c3edab9535d3f0903873f7", + "tests/ws_subscriptions/test_reviewer.c": "65916f6af7fb3fe00d00bf6999a55f441422b35d4d95b3f801d9cb9b0f591c54" + }, + "patch_sha256": "f7c97098339577e4343644d6730878da673de1fb1576b742330f89e04cb28baa" +} diff --git a/docs/repair/ws-operation/changes.patch b/docs/repair/ws-operation/changes.patch new file mode 100644 index 0000000..34e4680 --- /dev/null +++ b/docs/repair/ws-operation/changes.patch @@ -0,0 +1,3215 @@ +diff --git a/components/ts_webui/CMakeLists.txt b/components/ts_webui/CMakeLists.txt +index 666c0de..0fd6e09 100644 +--- a/components/ts_webui/CMakeLists.txt ++++ b/components/ts_webui/CMakeLists.txt +@@ -5,6 +5,7 @@ idf_component_register( + "src/ts_webui_ws.c" + "src/ts_ws_subscriptions.c" + "src/ts_ws_transport.c" ++ "src/ts_ws_operation.c" + INCLUDE_DIRS + "include" + REQUIRES +diff --git a/components/ts_webui/include/ts_ws_subscriptions.h b/components/ts_webui/include/ts_ws_subscriptions.h +index 1f9b169..2f872ac 100644 +--- a/components/ts_webui/include/ts_ws_subscriptions.h ++++ b/components/ts_webui/include/ts_ws_subscriptions.h +@@ -69,3 +69,7 @@ void ts_ws_broadcast_to_topic(const char *topic, cJSON *data); + #ifdef __cplusplus + } + #endif ++ ++/* Stable existing worker wake; does not allocate or start a new task. */ ++void ts_ws_subscriptions_wake(void); ++bool ts_ws_subscriptions_in_context(void); +diff --git a/components/ts_webui/include/ts_ws_transport.h b/components/ts_webui/include/ts_ws_transport.h +index bbd37ee..6f4ee12 100644 +--- a/components/ts_webui/include/ts_ws_transport.h ++++ b/components/ts_webui/include/ts_ws_transport.h +@@ -125,3 +125,7 @@ esp_err_t ts_ws_power_reserve(bool tick, ts_ws_reservation_t *r); + esp_err_t ts_ws_power_publish(ts_ws_reservation_t *r, const char *text); + + esp_err_t ts_ws_result_publish(ts_ws_reservation_t *r,const ts_ws_peer_t *peers,unsigned count); ++ ++/* Bind an original terminal recipient before transferring its reserved target. */ ++esp_err_t ts_ws_reserved_target(ts_ws_reservation_t *r, unsigned index, ts_ws_peer_t peer, ++ uint64_t revision, uint64_t delivery, ts_ws_delivery_done_t done); +diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c +index 6d0f56c..e8c2a9c 100644 +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -14,7 +14,10 @@ + #include "ts_keystore.h" + #include "ts_ws_subscriptions.h" + #include "ts_ws_transport.h" ++#include "ts_ws_operation.h" ++#include "freertos/timers.h" + #include ++#include + #include "esp_timer.h" + // ts_var.h 已废弃,统一使用 ts_variable.h(ts_automation 变量系统) + #include "ts_variable.h" +@@ -65,7 +68,6 @@ typedef struct { + + static ws_client_t s_clients[MAX_WS_CLIENTS]; + static _Atomic(httpd_handle_t) s_server = NULL; +-static ts_ws_peer_t s_ssh_peer; + static atomic_bool s_ws_stopping; + static SemaphoreHandle_t s_terminal_mutex = NULL; + static int s_terminal_client_fd = -1; // 当前终端会话的 fd +@@ -75,36 +77,14 @@ static char *s_terminal_output_buf = NULL; + static size_t s_terminal_output_len = 0; + static SemaphoreHandle_t s_output_mutex = NULL; + +-/* SSH Shell 会话状态 */ +-static ts_ssh_session_t s_ssh_session = NULL; +-static ts_ssh_shell_t s_ssh_shell = NULL; +-static atomic_int s_ssh_client_fd = -1; +-static atomic_bool s_ssh_running = false; +-static atomic_bool s_ssh_poll_alive; +-enum { SSH_IDLE, SSH_STARTING, SSH_READY, SSH_TERMINAL }; +-static atomic_uint s_ssh_state, s_ssh_generation, s_ssh_result_pending; +-static ts_ws_reservation_t s_ssh_terminal; +-static ts_ws_reservation_t s_exec_terminal; +-/* One producer per stream. Pending includes each accepted destination, including +- * publication callbacks that can run before submit returns. Terminal buffers +- * are not published/released until all earlier output has settled. */ +-static atomic_uint s_ssh_output_pending, s_exec_output_pending; +-static atomic_bool s_ssh_output_failed, s_exec_output_failed; +-static atomic_bool s_ssh_terminal_ready, s_exec_terminal_ready, s_exec_result_active, s_exec_terminal_claimed; +-static ts_ws_peer_t s_exec_result_peers[TS_WS_CONNECTIONS]; +-static unsigned s_exec_result_count; +-static void ssh_terminal_flush(void); +-static void ssh_exec_terminal_flush(void); +-static void ssh_exec_terminal_publish(const char *json,uint32_t session_id); +- +-/* SSH Exec 流式执行状态 */ +-static ts_ssh_session_t s_exec_session = NULL; +-static TaskHandle_t s_exec_task = NULL; +-static atomic_bool s_exec_running = false; +-static atomic_uint s_exec_creators; +-static volatile bool s_exec_cancel_requested = false; /* 实时匹配触发的取消请求 */ +-static volatile uint32_t s_exec_session_id = 0; +-static TimerHandle_t s_exec_timeout_timer = NULL; /* 超时定时器 */ ++/* Business resources belong to the operation held by task args and borrowers. */ ++typedef struct { ++ ts_ws_operation_t *op; ++ ts_ssh_session_t session; ++ ts_ssh_shell_t shell; ++ SemaphoreHandle_t io; ++ atomic_bool disconnect_requested; ++} ssh_shell_context_t; + + /* 电压保护事件处理器句柄 */ + static ts_event_handler_handle_t s_power_event_handle = NULL; +@@ -117,6 +97,7 @@ static atomic_bool s_log_streaming_enabled = false; + static const char *s_level_names[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"}; + + /* 前向声明 */ ++static void exec_retry_timer_drain(void); + static void update_log_stream_state(void); + esp_err_t ts_webui_log_stream_enable(bool enable); + esp_err_t ts_webui_ws_stop(httpd_handle_t server); +@@ -194,22 +175,6 @@ static void power_policy_event_handler(const ts_event_t *event, void *user_data) + /* SSH Shell Functions */ + /*===========================================================================*/ + +-static void ssh_terminal_done(uint64_t generation,uint64_t unused,esp_err_t result) +-{ +- (void)unused; +- unsigned expected=(unsigned)generation; +- atomic_compare_exchange_strong(&s_ssh_result_pending,&expected,0); +- if(result!=ESP_OK)TS_LOGW(TAG,"SSH terminal send failed: %s",esp_err_to_name(result)); +-} +-static bool ssh_generation_valid(uint64_t generation, uint64_t unused) +-{ +- (void)unused;return generation==s_ssh_generation; +-} +-static bool ssh_status_valid(uint64_t generation, uint64_t state) +-{ +- return generation==s_ssh_generation && state==s_ssh_state; +-} +-static esp_err_t ssh_send_status(const char *status, const char *message); + /* Request errors must go to the requester, never mutate an existing session. */ + static void ssh_request_error(httpd_req_t *req, const char *message) + { +@@ -224,365 +189,164 @@ static void ssh_request_error(httpd_req_t *req, const char *message) + free(json); + } + +-static void ssh_output_done(uint64_t generation,uint64_t delivery,esp_err_t result) ++static void shell_resources_close(ssh_shell_context_t *ctx) + { +- (void)delivery; /* transport already validates full peer identity */ +- if(generation!=s_ssh_generation)return; +- if(result!=ESP_OK){s_ssh_output_failed=true;s_ssh_running=false;} +- atomic_fetch_sub(&s_ssh_output_pending,1); +- if(result!=ESP_OK)ssh_send_status("error","SSH output delivery incomplete; remote command result is not confirmed"); +- ssh_terminal_flush(); ++ xSemaphoreTake(ctx->io,portMAX_DELAY); ++ if(ctx->shell){ts_ssh_shell_close(ctx->shell);ctx->shell=NULL;} ++ if(ctx->session){ts_ssh_disconnect(ctx->session);ts_ssh_session_destroy(ctx->session);ctx->session=NULL;} ++ xSemaphoreGive(ctx->io); + } +-static void ssh_terminal_flush(void) ++static void shell_destroy(void *data) + { +- if(s_ssh_output_pending)return; +- bool ready=true; +- if(!atomic_compare_exchange_strong(&s_ssh_terminal_ready,&ready,false))return; +- unsigned generation=s_ssh_generation; +- if(s_ssh_output_failed)ts_ws_reserved_text(&s_ssh_terminal, +- "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}"); +- ts_ws_reservation_t terminal=s_ssh_terminal; +- s_ssh_terminal=(ts_ws_reservation_t){0}; +- esp_err_t ret=ts_ws_reserved_submit(&terminal,0,generation,SSH_TERMINAL,ssh_status_valid,ssh_terminal_done); +- if(ret!=ESP_OK)ssh_terminal_done(generation,SSH_TERMINAL,ret); +- ts_ws_reservation_release(&terminal); ++ ssh_shell_context_t *ctx=data; ++ if(!ctx)return; ++ /* Network cleanup belongs to the creator/poller, never the TX worker. */ ++ assert(!ctx->session && !ctx->shell); ++ vSemaphoreDelete(ctx->io);free(ctx); + } +- +-/* 发送 SSH 输出到 WebSocket 客户端 */ +-static void ssh_send_output(const char *data, size_t len) ++static void ssh_close(ts_ws_operation_t *op,const char *status,const char *message) + { +- if(s_ssh_client_fd<0 || !s_server || !data || !len || s_ssh_state!=SSH_READY)return; +- esp_err_t ret=ESP_ERR_NO_MEM; +- char *buf=heap_caps_malloc(len+1,MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); +- if(!buf)buf=malloc(len+1); +- cJSON *msg=NULL; +- char *json=NULL; +- if(buf) { +- memcpy(buf,data,len);buf[len]=0; +- msg=cJSON_CreateObject(); +- if(msg && cJSON_AddStringToObject(msg,"type","ssh_output") && cJSON_AddStringToObject(msg,"data",buf)) +- json=cJSON_PrintUnformatted(msg); +- } +- free(buf);cJSON_Delete(msg); +- if(json) { +- ts_ws_message_t *m=ts_ws_message_text(json,strlen(json)); +- if(m) { +- atomic_fetch_add(&s_ssh_output_pending,1); +- ret=ts_ws_transport_submit(s_ssh_peer,m,s_ssh_generation,s_ssh_peer.connection,ssh_generation_valid,ssh_output_done); +- /* Rejection was never accepted and has no completion callback. */ +- if(ret!=ESP_OK)ssh_output_done(s_ssh_generation,s_ssh_peer.connection,ret); +- } +- ts_ws_message_release(m); +- } +- free(json); +- if(ret!=ESP_OK) { +- s_ssh_output_failed=true; +- TS_LOGW(TAG,"SSH output rejected: %s",esp_err_to_name(ret)); +- ssh_send_status("error","SSH output delivery failed"); +- s_ssh_running=false; +- } ++ if(!ts_ws_op_close_begin(op))return; ++ cJSON *msg=cJSON_CreateObject(); ++ bool ok=msg && cJSON_AddStringToObject(msg,"type","ssh_status") && ++ cJSON_AddStringToObject(msg,"status",status) && cJSON_AddStringToObject(msg,"message",message); ++ char *json=ok?cJSON_PrintUnformatted(msg):NULL;cJSON_Delete(msg); ++ ts_ws_op_close_finish(op,json);free(json); + } +- +-/* 发送 SSH 状态消息 */ +-static esp_err_t ssh_send_status(const char *status, const char *message) ++static void ssh_send_output(ssh_shell_context_t *ctx,const char *data,size_t len) ++{ ++ if(!data || !len)return; ++ ts_ws_output_ticket_t ticket; ++ if(!ts_ws_op_output_begin(ctx->op,&ticket))return; ++ char *buf=NULL,*json=NULL;cJSON *msg=NULL; ++ if(ticket.count) { ++ buf=heap_caps_malloc(len+1,MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); ++ if(!buf)buf=malloc(len+1); ++ if(buf){memcpy(buf,data,len);buf[len]=0;msg=cJSON_CreateObject(); ++ if(msg && cJSON_AddStringToObject(msg,"type","ssh_output") && cJSON_AddStringToObject(msg,"data",buf))json=cJSON_PrintUnformatted(msg);} ++ } ++ free(buf);cJSON_Delete(msg);ts_ws_op_output_finish(&ticket,json);free(json); ++} ++/* Startup controls are synchronous on the HTTPD owner. Creator + poller refs ++ * pin STARTING; OPEN is published only after connected has returned successfully. ++ * They cannot be overtaken by ordinary output or an asynchronous close callback. */ ++static esp_err_t ssh_start_status(ssh_shell_context_t *ctx,const char *status,const char *message) + { +- bool terminal=!strcmp(status,"error") || !strcmp(status,"closed"); +- unsigned state=!strcmp(status,"connecting") ? SSH_STARTING : SSH_READY; +- unsigned generation=s_ssh_generation; +- if(terminal) { +- unsigned previous=atomic_exchange(&s_ssh_state,SSH_TERMINAL); +- if(previous==SSH_TERMINAL)return ESP_OK; +- state=SSH_TERMINAL; +- } else if(!ssh_status_valid(generation,state)) return ESP_ERR_INVALID_STATE; ++ if(!ts_ws_op_starting(ctx->op))return ESP_ERR_INVALID_STATE; + cJSON *msg=cJSON_CreateObject(); + bool ok=msg && cJSON_AddStringToObject(msg,"type","ssh_status") && +- cJSON_AddStringToObject(msg,"status",status) && (!message || cJSON_AddStringToObject(msg,"message",message)); +- char *json=ok ? cJSON_PrintUnformatted(msg) : NULL; +- cJSON_Delete(msg); ++ cJSON_AddStringToObject(msg,"status",status) && cJSON_AddStringToObject(msg,"message",message); ++ char *json=ok?cJSON_PrintUnformatted(msg):NULL;cJSON_Delete(msg); + esp_err_t ret=ESP_ERR_NO_MEM; +- if(terminal) { +- const char *fallback="{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH status delivery failed\"}"; +- ret=ts_ws_reserved_text(&s_ssh_terminal,json?json:fallback); +- if(ret!=ESP_OK) { +- TS_LOGW(TAG,"SSH terminal encoding failed: %s",esp_err_to_name(ret)); +- ret=ts_ws_reserved_text(&s_ssh_terminal,fallback); +- } +- s_ssh_result_pending=generation; +- if(ret==ESP_OK){s_ssh_terminal_ready=true;ssh_terminal_flush();} +- else {ssh_terminal_done(generation,state,ret);ts_ws_reservation_release(&s_ssh_terminal);} +- } else if(json && ssh_status_valid(generation,state)) { +- httpd_ws_frame_t frame={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)json,.len=strlen(json)}; +- if(ts_ws_transport_in_context()) ret=ts_ws_transport_send(s_ssh_peer.server,s_ssh_peer.fd,&frame); +- else { +- ts_ws_message_t *m=ts_ws_message_text(json,strlen(json)); +- if(m) {ret=ts_ws_transport_submit(s_ssh_peer,m,generation,state,ssh_status_valid,NULL);ts_ws_message_release(m);} +- } +- } +- free(json); +- if(ret!=ESP_OK)TS_LOGW(TAG,"SSH status rejected: %s",esp_err_to_name(ret)); +- return ret; ++ if(json){ts_ws_peer_t peer=ts_ws_op_peer(ctx->op);httpd_ws_frame_t f={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)json,.len=strlen(json)}; ++ ret=ts_ws_transport_send(peer.server,peer.fd,&f);} ++ free(json);return ret; ++} ++/* Poller remains the only ordinary observation producer. User disconnect is ++ * handed to that producer, preserving the disconnecting/closed wire messages. */ ++static void ssh_disconnecting(ssh_shell_context_t *ctx) ++{ ++ ts_ws_output_ticket_t ticket; ++ if(ts_ws_op_output_begin(ctx->op,&ticket)) ++ ts_ws_op_output_finish(&ticket,"{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}"); ++ ssh_close(ctx->op,"closed","SSH session closed"); + } +- +-/* 前向声明 */ +-static void ssh_cleanup(void); +- +-/* SSH Shell 轮询任务 */ + static void ssh_poll_task(void *arg) + { ++ ssh_shell_context_t *ctx=arg;ts_ws_operation_t *op=ctx->op; + char buf[SSH_OUTPUT_BUF_SIZE]; +- bool need_cleanup = false; +- +- TS_LOGD(TAG, "SSH poll task started"); +- +- while(s_ssh_running && s_ssh_state==SSH_STARTING) vTaskDelay(1); +- while (s_ssh_running && s_ssh_state==SSH_READY && s_ssh_shell) { +- size_t read_len = 0; +- esp_err_t ret = ts_ssh_shell_read(s_ssh_shell, buf, sizeof(buf) - 1, &read_len); +- +- if (ret == ESP_OK && read_len > 0) { +- buf[read_len] = '\0'; +- ssh_send_output(buf, read_len); +- } +- +- // 检查 shell 是否还活跃 +- if (!ts_ssh_shell_is_active(s_ssh_shell)) { +- TS_LOGD(TAG, "SSH shell closed by remote"); +- ssh_send_status("closed", "SSH session closed"); +- need_cleanup = true; // 标记需要清理 +- break; +- } +- +- vTaskDelay(pdMS_TO_TICKS(20)); // 50Hz 轮询 +- } +- +- TS_LOGD(TAG, "SSH poll task ended"); +- +- if(s_ssh_state==SSH_READY) ssh_send_status("closed","SSH session closed"); +- if(s_ssh_state==SSH_TERMINAL)need_cleanup=true; +- // 如果是因为远程关闭而退出,需要清理 SSH 会话 +- if (need_cleanup && s_ssh_session) { +- // 清理 shell(已经关闭,只需释放资源) +- if (s_ssh_shell) { +- ts_ssh_shell_close(s_ssh_shell); +- s_ssh_shell = NULL; +- } +- // 清理 session +- if (s_ssh_session) { +- ts_ssh_disconnect(s_ssh_session); +- ts_ssh_session_destroy(s_ssh_session); +- s_ssh_session = NULL; +- } +- /* Legacy UI type is changed only by the HTTPD owner. A retired SSH +- * worker must not change a replacement connection that reuses its fd. */ +- s_ssh_client_fd = -1; +- TS_LOGD(TAG, "SSH session cleaned up after remote close"); +- } +- +- s_ssh_poll_alive = false; ++ while(ts_ws_op_starting(op))vTaskDelay(1); ++ while(ts_ws_op_is_open(op)) { ++ if(ctx->disconnect_requested){ssh_disconnecting(ctx);break;} ++ size_t n=0; ++ xSemaphoreTake(ctx->io,portMAX_DELAY); ++ esp_err_t ret=ts_ssh_shell_read(ctx->shell,buf,sizeof(buf)-1,&n); ++ bool active=ts_ssh_shell_is_active(ctx->shell); ++ xSemaphoreGive(ctx->io); ++ if(ret==ESP_OK && n)ssh_send_output(ctx,buf,n); ++ if(!active){ssh_close(op,"closed","SSH session closed");break;} ++ vTaskDelay(pdMS_TO_TICKS(20)); ++ } ++ shell_resources_close(ctx); ++ ts_ws_op_executor_done(op); + vTaskDelete(NULL); + } +- +-/* 清理 SSH 会话 */ + static void ssh_cleanup(void) + { +- s_ssh_running = false; +- +- int64_t deadline = esp_timer_get_time() + 2000000; +- while (s_ssh_poll_alive) { +- if (esp_timer_get_time() >= deadline) return; /* retain resources for retry */ +- vTaskDelay(1); +- } +- +- if (s_ssh_shell) { +- ts_ssh_shell_close(s_ssh_shell); +- s_ssh_shell = NULL; +- } +- +- if (s_ssh_session) { +- ts_ssh_disconnect(s_ssh_session); +- ts_ssh_session_destroy(s_ssh_session); +- s_ssh_session = NULL; +- } +- +- // 更新客户端类型 +- if (s_ssh_client_fd >= 0) { +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { +- set_client_role(s_ssh_peer, WS_CLIENT_TYPE_TERMINAL, TS_LOG_NONE); +- break; +- } +- } +- } +- if(s_ssh_state==SSH_READY) ssh_send_status("closed","SSH session closed"); +- s_ssh_client_fd = -1; +- if(!s_ssh_result_pending && !s_ssh_output_pending)ts_ws_reservation_release(&s_ssh_terminal); +- +- TS_LOGD(TAG, "SSH session cleaned up"); ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0); ++ if(!op)return; ++ ssh_close(op,"closed","SSH session closed"); ++ ts_ws_op_release(op); + } +- +-/* 处理 SSH Shell 连接请求 */ +-static void handle_ssh_connect(httpd_req_t *req, cJSON *params) ++static void handle_ssh_connect(httpd_req_t *req,cJSON *params) + { +- if (s_ssh_result_pending || s_ssh_output_pending) { +- ssh_request_error(req,"Previous SSH result is still pending"); +- return; +- } +- if (s_ssh_poll_alive) { +- ssh_request_error(req, "Another SSH session is active"); +- return; +- } +- +- int fd = httpd_req_to_sockfd(req); +- +- // 检查是否已有 SSH 会话 +- if (s_ssh_session != NULL) { +- ssh_request_error(req, "Another SSH session is active"); +- return; +- } +- +- // 解析参数 +- cJSON *host = cJSON_GetObjectItem(params, "host"); +- cJSON *port = cJSON_GetObjectItem(params, "port"); +- cJSON *user = cJSON_GetObjectItem(params, "user"); +- cJSON *password = cJSON_GetObjectItem(params, "password"); +- +- if (!host || !cJSON_IsString(host) || !user || !cJSON_IsString(user)) { +- ssh_request_error(req, "Missing host or user"); +- return; +- } +- +- int ssh_port = (port && cJSON_IsNumber(port)) ? port->valueint : 22; +- const char *ssh_password = (password && cJSON_IsString(password)) ? password->valuestring : ""; +- +- TS_LOGD(TAG, "SSH connect: %s@%s:%d", user->valuestring, host->valuestring, ssh_port); +- +- ts_ws_peer_t peer=*(ts_ws_peer_t *)req->sess_ctx; +- if(s_ssh_generation==UINT32_MAX || ts_ws_reserve(&peer,1,true,4096,&s_ssh_terminal)!=ESP_OK) { +- ssh_request_error(req,"SSH result delivery capacity unavailable"); +- return; +- } +- s_ssh_output_failed=false; +- s_ssh_terminal_ready=false; +- s_ssh_generation++; +- s_ssh_state=SSH_STARTING; +- // 设置 SSH 客户端 fd +- s_ssh_peer = *(ts_ws_peer_t *)req->sess_ctx; +- s_ssh_client_fd = fd; +- +- // 更新客户端类型 +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == fd) { +- set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_SSH_SHELL, TS_LOG_NONE); +- break; +- } +- } +- +- // 发送连接中状态 +- if(ssh_send_status("connecting", "Connecting to SSH server...")!=ESP_OK) { +- ssh_send_status("error","SSH connection status delivery failed"); +- ssh_cleanup();return; +- } +- +- // 配置 SSH +- ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); +- config.host = host->valuestring; +- config.port = ssh_port; +- config.username = user->valuestring; +- config.auth_method = TS_SSH_AUTH_PASSWORD; +- config.auth.password = ssh_password; +- config.timeout_ms = 10000; +- +- // 创建会话 +- esp_err_t ret = ts_ssh_session_create(&config, &s_ssh_session); +- if (ret != ESP_OK) { +- ssh_send_status("error", "Failed to create SSH session"); +- ssh_cleanup(); +- return; +- } +- +- // 连接 +- ret = ts_ssh_connect(s_ssh_session); +- if (ret != ESP_OK) { +- char err_msg[128]; +- snprintf(err_msg, sizeof(err_msg), "Connection failed: %s", ts_ssh_get_error(s_ssh_session)); +- ssh_send_status("error", err_msg); +- ssh_cleanup(); +- return; +- } +- +- // 打开 Shell +- ts_shell_config_t shell_config = TS_SHELL_DEFAULT_CONFIG(); +- shell_config.term_width = 80; +- shell_config.term_height = 24; +- shell_config.read_timeout_ms = 50; +- +- ret = ts_ssh_shell_open(s_ssh_session, &shell_config, &s_ssh_shell); +- if (ret != ESP_OK) { +- ssh_send_status("error", "Failed to open shell"); +- ssh_cleanup(); +- return; +- } +- +- // 启动轮询任务(栈需要足够大以容纳 libssh2 缓冲区,使用 PSRAM) +- s_ssh_running = true; +- s_ssh_poll_alive = true; +- if (xTaskCreateWithCaps(ssh_poll_task, "ssh_poll", 4096, NULL, 5, NULL, MALLOC_CAP_SPIRAM) != pdPASS) { +- s_ssh_poll_alive = false; +- ssh_send_status("error", "Failed to create SSH session"); +- ssh_cleanup(); +- return; +- } +- /* A created task alone is not readiness: the current shell must still be +- * active. The poller cannot emit output/closed until STARTING has ended. */ +- if(!ts_ssh_shell_is_active(s_ssh_shell)) { +- ssh_send_status("error","SSH shell closed during startup"); +- ssh_cleanup();return; +- } +- unsigned expected=SSH_STARTING; +- if(!atomic_compare_exchange_strong(&s_ssh_state,&expected,SSH_READY)) { +- ssh_cleanup();return; +- } +- esp_err_t ready=ssh_send_status("connected","SSH shell ready"); +- if(ready!=ESP_OK && s_ssh_state==SSH_READY) { +- ssh_send_status("error","SSH readiness delivery failed"); +- ssh_cleanup(); +- } ++ cJSON *host=cJSON_GetObjectItem(params,"host"),*user=cJSON_GetObjectItem(params,"user"); ++ cJSON *port=cJSON_GetObjectItem(params,"port"),*password=cJSON_GetObjectItem(params,"password"); ++ if(!cJSON_IsString(host) || !cJSON_IsString(user)){ssh_request_error(req,"Missing host or user");return;} ++ ts_ws_peer_t peer=*(ts_ws_peer_t*)req->sess_ctx; ++ esp_err_t admission; ++ ts_ws_operation_t *op=ts_ws_op_create(TS_WS_OP_SHELL,peer,&admission); ++ if(!op){ssh_request_error(req,admission==ESP_ERR_NO_MEM?"SSH result delivery capacity unavailable":"Another SSH session is active");return;} ++ ssh_shell_context_t *ctx=calloc(1,sizeof(*ctx)); ++ if(!ctx || !(ctx->io=xSemaphoreCreateMutex())) { ++ free(ctx);ts_ws_op_discard(op);ts_ws_op_executor_done(op);ssh_request_error(req,"Failed to create SSH session");return; ++ } ++ ctx->op=op;ts_ws_op_bind(op,ctx,shell_destroy); ++ set_client_role(peer,WS_CLIENT_TYPE_SSH_SHELL,TS_LOG_NONE); ++ const char *error="SSH connection status delivery failed";bool poller=false; ++ if(ssh_start_status(ctx,"connecting","Connecting to SSH server...")!=ESP_OK)goto failed; ++ ts_ssh_config_t config=TS_SSH_DEFAULT_CONFIG(); ++ config.host=host->valuestring;config.username=user->valuestring; ++ config.port=cJSON_IsNumber(port)?port->valueint:22; ++ config.auth_method=TS_SSH_AUTH_PASSWORD;config.auth.password=cJSON_IsString(password)?password->valuestring:"";config.timeout_ms=10000; ++ error="Failed to create SSH session"; ++ if(ts_ssh_session_create(&config,&ctx->session)!=ESP_OK)goto failed; ++ if(ts_ssh_connect(ctx->session)!=ESP_OK){error=ts_ssh_get_error(ctx->session);goto failed;} ++ ts_shell_config_t shell_config=TS_SHELL_DEFAULT_CONFIG();shell_config.term_width=80;shell_config.term_height=24;shell_config.read_timeout_ms=50; ++ error="Failed to open shell"; ++ if(ts_ssh_shell_open(ctx->session,&shell_config,&ctx->shell)!=ESP_OK)goto failed; ++ ts_ws_op_executor_take(op); ++ if(xTaskCreateWithCaps(ssh_poll_task,"ssh_poll",4096,ctx,5,NULL,MALLOC_CAP_SPIRAM)!=pdPASS){ts_ws_op_executor_done(op);error="Failed to create SSH session";goto failed;} ++ poller=true;error="SSH shell closed during startup"; ++ if(!ts_ssh_shell_is_active(ctx->shell))goto failed; ++ error="SSH readiness delivery failed"; ++ if(ssh_start_status(ctx,"connected","SSH shell ready")!=ESP_OK)goto failed; ++ ts_ws_op_open(op);ts_ws_op_executor_done(op);return; ++failed: ++ ssh_close(op,"error",error?error:"SSH connection failed"); ++ if(!poller)shell_resources_close(ctx); ++ set_client_role(peer,WS_CLIENT_TYPE_TERMINAL,TS_LOG_NONE); ++ ts_ws_op_executor_done(op); + } +- +-/* 处理 SSH Shell 输入 */ ++/* Input borrows the original context. Cleanup takes the same resource mutex; ++ * the lifecycle lock is never held across SSH I/O. */ + static void handle_ssh_input(const char *data) + { +- if (!s_ssh_shell || !data) return; +- +- size_t len = strlen(data); +- if (len == 0) return; +- +- ts_ssh_shell_write(s_ssh_shell, data, len, NULL); ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; ++ ssh_shell_context_t *ctx=ts_ws_op_data(op); ++ if(ctx && data){xSemaphoreTake(ctx->io,portMAX_DELAY);if(ctx->shell && ts_ws_op_is_open(op))ts_ssh_shell_write(ctx->shell,data,strlen(data),NULL);xSemaphoreGive(ctx->io);} ++ ts_ws_op_release(op); + } +- +-/* 处理 SSH Shell 断开 */ + static void handle_ssh_disconnect(void) + { +- if (s_ssh_session) { +- ssh_send_status("disconnecting", "Closing SSH session..."); +- ssh_cleanup(); +- } ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; ++ ssh_shell_context_t *ctx=ts_ws_op_data(op); ++ if(ctx)ctx->disconnect_requested=true; ++ ts_ws_op_release(op); + } +- +-/* 处理 SSH Shell 信号 */ + static void handle_ssh_signal(const char *signal) + { +- if (s_ssh_shell && signal) { +- ts_ssh_shell_send_signal(s_ssh_shell, signal); +- } ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; ++ ssh_shell_context_t *ctx=ts_ws_op_data(op); ++ if(ctx && signal){xSemaphoreTake(ctx->io,portMAX_DELAY);if(ctx->shell && ts_ws_op_is_open(op))ts_ssh_shell_send_signal(ctx->shell,signal);xSemaphoreGive(ctx->io);} ++ ts_ws_op_release(op); + } +- +-/* 处理 SSH Shell 窗口大小调整 */ +-static void handle_ssh_resize(int width, int height) ++static void handle_ssh_resize(int width,int height) + { +- if (s_ssh_shell && width > 0 && height > 0) { +- ts_ssh_shell_resize(s_ssh_shell, width, height); +- } ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0);if(!op)return; ++ ssh_shell_context_t *ctx=ts_ws_op_data(op); ++ if(ctx && width>0 && height>0){xSemaphoreTake(ctx->io,portMAX_DELAY);if(ctx->shell && ts_ws_op_is_open(op))ts_ssh_shell_resize(ctx->shell,width,height);xSemaphoreGive(ctx->io);} ++ ts_ws_op_release(op); + } + + /*===========================================================================*/ +@@ -825,10 +589,6 @@ static void cleanup_disconnected_client(int fd) + xSemaphoreGive(s_terminal_mutex); + } + } +- // 如果是 SSH Shell 客户端,清理 SSH 会话 +- if (s_clients[i].type == WS_CLIENT_TYPE_SSH_SHELL && s_ssh_client_fd == fd) { +- ssh_cleanup(); +- } + // 检查是否是日志客户端 + if (s_clients[i].type == WS_CLIENT_TYPE_LOG) { + was_log_client = true; +@@ -848,6 +608,8 @@ static void cleanup_disconnected_client(int fd) + static void peer_closed(ts_ws_peer_t peer) + { + ts_ws_client_disconnected(peer); ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_SHELL,0); ++ if(op){if(ts_ws_peer_equal(ts_ws_op_peer(op),peer))ssh_close(op,"closed","SSH session closed");ts_ws_op_release(op);} + cleanup_disconnected_client(peer.fd); + } + +@@ -1271,22 +1033,32 @@ esp_err_t ts_webui_ws_init(void) + } + } + ++ ts_ws_op_enable(); + TS_LOGI(TAG, "WebSocket handler registered at /ws"); + return ESP_OK; + } + + esp_err_t ts_webui_ws_stop(httpd_handle_t server) + { +- if (ts_ws_transport_in_context() || ts_event_in_callback()) return ESP_ERR_INVALID_STATE; ++ if (ts_ws_transport_in_context() || ts_event_in_callback() || ts_ws_subscriptions_in_context()) return ESP_ERR_INVALID_STATE; ++ ts_ws_op_stop_admission(); ++ exec_retry_timer_drain(); + s_ws_stopping = true; + esp_err_t ret = ts_ws_subscriptions_pause(); + if (ret != ESP_OK) return ret; + ret = ts_ws_transport_quiesce(server, 6000); + if (ret != ESP_OK) return ret; + /* The worker still sends results even when this attempt returns busy. */ +- if (s_exec_creators || s_exec_running) return ESP_ERR_INVALID_STATE; + ssh_cleanup(); +- if (s_ssh_poll_alive) return ESP_ERR_TIMEOUT; ++ ts_ws_operation_t *exec=ts_ws_op_acquire(TS_WS_OP_EXEC,0); ++ bool executing=exec && ts_ws_op_executing(exec); ++ if(exec)ts_ws_op_release(exec); ++ if(executing)return ESP_ERR_INVALID_STATE; /* never cancel the remote job to stop WebUI */ ++ int64_t deadline=esp_timer_get_time()+2000000; ++ while(ts_ws_op_busy()) { ++ if(esp_timer_get_time()>=deadline)return ESP_ERR_TIMEOUT; ++ vTaskDelay(1); /* producer, callbacks, timer daemon and sender remain alive */ ++ } + if (s_power_event_handle) { + ret = ts_event_unregister_sync(s_power_event_handle, 6000); + if (ret != ESP_OK && ret != ESP_ERR_NOT_FOUND) return ret; +@@ -1296,7 +1068,7 @@ esp_err_t ts_webui_ws_stop(httpd_handle_t server) + if (ret != ESP_OK) return ret; + ret = ts_ws_subscriptions_drain(); + if (ret != ESP_OK) return ret; +- if(s_exec_result_active || s_ssh_result_pending || s_ssh_output_pending)return ESP_ERR_INVALID_STATE; ++ if(ts_ws_op_busy())return ESP_ERR_INVALID_STATE; + ret = ts_ws_transport_stop(server, 6000); + if (ret != ESP_OK) return ret; + return ts_ws_subscriptions_deinit(); +@@ -1451,6 +1223,15 @@ static void update_log_stream_state(void) + + /* SSH Exec 任务参数 */ + typedef struct { ++ ts_ws_operation_t *op; ++ ts_ssh_session_t session; ++ SemaphoreHandle_t io; ++ TimerHandle_t timer; ++ atomic_bool cancel_requested, timer_closing; ++ atomic_uint timer_phase; /* 0 none, 1 live, 2 delete, 3 barrier, 4 queued, 5 drained */ ++ atomic_uint timer_retries; ++ int64_t timer_retry_at; /* maintenance worker owns pacing */ ++ char *password_owned; + ts_ssh_config_t config; + char command[512]; + uint32_t session_id; +@@ -1475,9 +1256,6 @@ typedef struct { + char *extracted_value; /* 提取的值 */ + } ssh_exec_task_params_t; + +-/* 全局任务参数指针(用于回调访问) */ +-static ssh_exec_task_params_t *s_exec_params = NULL; +- + /* 简单的正则表达式匹配(支持基本模式)*/ + static bool simple_pattern_match(const char *text, const char *pattern, char **extracted) + { +@@ -1555,49 +1333,35 @@ static bool simple_pattern_match(const char *text, const char *pattern, char **e + } + } + +-static void ssh_exec_output_done(uint64_t session,uint64_t connection,esp_err_t result) +-{ +- (void)connection; +- if(session!=s_exec_session_id)return; +- if(result!=ESP_OK)s_exec_output_failed=true; +- atomic_fetch_sub(&s_exec_output_pending,1); +- if(result!=ESP_OK)ssh_exec_terminal_publish(NULL,(uint32_t)session); +- ssh_exec_terminal_flush(); +-} +-static void ssh_exec_stream_publish(const char *json,uint32_t session) ++static void exec_abort(ssh_exec_task_params_t *params) + { +- if(session!=s_exec_session_id || s_exec_output_failed)return; +- ts_ws_peer_t peers[TS_WS_CONNECTIONS]; +- unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); +- if(!n)return; +- ts_ws_message_t *m=json?ts_ws_message_text(json,strlen(json)):NULL; +- if(!m){s_exec_output_failed=true;ssh_exec_terminal_publish(NULL,session);return;} +- atomic_fetch_add(&s_exec_output_pending,n); /* register the whole fanout before any early callback */ +- for(unsigned i=0;iio,portMAX_DELAY); ++ if(params->session)ts_ssh_abort(params->session); ++ xSemaphoreGive(params->io); + } +- + /* SSH Exec 输出回调 - 广播到所有 WebSocket 客户端并收集输出 */ + static void ssh_exec_output_callback(const char *data, size_t len, bool is_stderr, void *user_data) + { + if (!data || len == 0) return; + +- uint32_t session_id = (uint32_t)(uintptr_t)user_data; ++ ssh_exec_task_params_t *params=user_data; ++ ts_ws_op_retain(params->op); /* synchronous SSH callback borrows executor-owned params */ ++ uint32_t session_id=params->session_id; + + /* 收集输出到缓冲区 */ +- if (s_exec_params && s_exec_params->collect_output && s_exec_params->output_buffer) { +- size_t space = s_exec_params->output_capacity - s_exec_params->output_len - 1; ++ if (params && params->collect_output && params->output_buffer) { ++ size_t space = params->output_capacity - params->output_len - 1; + size_t copy_len = (len < space) ? len : space; + if (copy_len > 0) { +- memcpy(s_exec_params->output_buffer + s_exec_params->output_len, data, copy_len); +- s_exec_params->output_len += copy_len; +- s_exec_params->output_buffer[s_exec_params->output_len] = '\0'; ++ memcpy(params->output_buffer + params->output_len, data, copy_len); ++ params->output_len += copy_len; ++ params->output_buffer[params->output_len] = '\0'; + } + } + ++ ts_ws_output_ticket_t ticket; ++ if(ts_ws_op_output_begin(params->op,&ticket)) { ++ if(ticket.count) { + cJSON *msg=cJSON_CreateObject(); + char *buf=heap_caps_malloc(len+1,MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + if(!buf)buf=malloc(len+1); +@@ -1607,21 +1371,24 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + cJSON_AddStringToObject(msg,"data",buf); + char *json=encoded?cJSON_PrintUnformatted(msg):NULL; + free(buf);cJSON_Delete(msg); +- ssh_exec_stream_publish(json,session_id); ++ ts_ws_op_output_finish(&ticket,json); + free(json); + ++ } else ts_ws_op_output_finish(&ticket,NULL); ++ } ++ + /* 实时模式匹配 */ +- if (s_exec_params && s_exec_params->output_buffer) { +- const char *output = s_exec_params->output_buffer; ++ if (params && params->output_buffer) { ++ const char *output = params->output_buffer; + bool should_send_match = false; + bool pattern_matched = false; /* expect/fail 模式是否匹配 */ + bool is_first_extract = false; /* 是否为首次提取 */ + + /* 检查失败模式(仅在尚未匹配时) */ +- if (!s_exec_params->match_found && s_exec_params->fail_pattern && s_exec_params->fail_pattern[0]) { +- if (simple_pattern_match(output, s_exec_params->fail_pattern, NULL)) { +- s_exec_params->fail_matched = true; +- s_exec_params->match_found = true; ++ if (!params->match_found && params->fail_pattern && params->fail_pattern[0]) { ++ if (simple_pattern_match(output, params->fail_pattern, NULL)) { ++ params->fail_matched = true; ++ params->match_found = true; + should_send_match = true; + pattern_matched = true; + TS_LOGW(TAG, "Realtime fail pattern matched"); +@@ -1629,11 +1396,11 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + } + + /* 检查期望模式(仅在尚未匹配时,且失败模式没有匹配) */ +- if (!s_exec_params->match_found && !s_exec_params->fail_matched && +- s_exec_params->expect_pattern && s_exec_params->expect_pattern[0]) { +- if (simple_pattern_match(output, s_exec_params->expect_pattern, NULL)) { +- s_exec_params->expect_matched = true; +- s_exec_params->match_found = true; ++ if (!params->match_found && !params->fail_matched && ++ params->expect_pattern && params->expect_pattern[0]) { ++ if (simple_pattern_match(output, params->expect_pattern, NULL)) { ++ params->expect_matched = true; ++ params->match_found = true; + should_send_match = true; + pattern_matched = true; + TS_LOGI(TAG, "Realtime expect pattern matched"); +@@ -1641,11 +1408,11 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + } + + /* 提取值 */ +- if (s_exec_params->extract_pattern && s_exec_params->extract_pattern[0]) { ++ if (params->extract_pattern && params->extract_pattern[0]) { + char *extracted = NULL; +- if (simple_pattern_match(output, s_exec_params->extract_pattern, &extracted)) { ++ if (simple_pattern_match(output, params->extract_pattern, &extracted)) { + /* 检查是否为首次提取 */ +- if (!s_exec_params->extracted_value) { ++ if (!params->extracted_value) { + is_first_extract = true; + } + +@@ -1653,16 +1420,16 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + bool is_new_value = false; + if (is_first_extract) { + is_new_value = true; +- } else if (extracted && strcmp(extracted, s_exec_params->extracted_value) != 0) { ++ } else if (extracted && strcmp(extracted, params->extracted_value) != 0) { + is_new_value = true; + } + + if (is_new_value) { + /* 释放旧值,保存新值 */ +- if (s_exec_params->extracted_value) { +- free(s_exec_params->extracted_value); ++ if (params->extracted_value) { ++ free(params->extracted_value); + } +- s_exec_params->extracted_value = extracted; ++ params->extracted_value = extracted; + should_send_match = true; + TS_LOGI(TAG, "Realtime extract: %s (first=%d)", extracted ? extracted : "(null)", is_first_extract); + } else { +@@ -1674,7 +1441,7 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + + /* 判断是否应该停止 */ + bool should_stop = false; +- if (s_exec_params->stop_on_match) { ++ if (params->stop_on_match) { + /* 勾选了"匹配后停止":expect/fail 匹配 或 首次提取成功 都应该停止 */ + if (pattern_matched || is_first_extract) { + should_stop = true; +@@ -1683,22 +1450,28 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + + /* 发送实时匹配消息 */ + if (should_send_match) { ++ ts_ws_output_ticket_t match_ticket; ++ if(ts_ws_op_output_begin(params->op,&match_ticket)) { ++ if(match_ticket.count) { + cJSON *match_msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(match_msg, "type", "ssh_exec_match"); +- cJSON_AddNumberToObject(match_msg, "session_id", session_id); +- cJSON_AddBoolToObject(match_msg, "expect_matched", s_exec_params->expect_matched); +- cJSON_AddBoolToObject(match_msg, "fail_matched", s_exec_params->fail_matched); +- if (s_exec_params->extracted_value) { +- cJSON_AddStringToObject(match_msg, "extracted", s_exec_params->extracted_value); ++ bool match_encoded=match_msg!=NULL; ++ match_encoded = (cJSON_AddStringToObject(match_msg, "type", "ssh_exec_match"))!=NULL && match_encoded; ++ match_encoded = (cJSON_AddNumberToObject(match_msg, "session_id", session_id))!=NULL && match_encoded; ++ match_encoded = (cJSON_AddBoolToObject(match_msg, "expect_matched", params->expect_matched))!=NULL && match_encoded; ++ match_encoded = (cJSON_AddBoolToObject(match_msg, "fail_matched", params->fail_matched))!=NULL && match_encoded; ++ if (params->extracted_value) { ++ match_encoded = (cJSON_AddStringToObject(match_msg, "extracted", params->extracted_value))!=NULL && match_encoded; + } + /* 标记是否为终止匹配 */ +- cJSON_AddBoolToObject(match_msg, "is_final", should_stop); ++ match_encoded = (cJSON_AddBoolToObject(match_msg, "is_final", should_stop))!=NULL && match_encoded; + +- char *match_json = cJSON_PrintUnformatted(match_msg); ++ char *match_json = match_encoded?cJSON_PrintUnformatted(match_msg):NULL; + cJSON_Delete(match_msg); +- ssh_exec_stream_publish(match_json,session_id); ++ ts_ws_op_output_finish(&match_ticket,match_json); + free(match_json); + ++ } else ts_ws_op_output_finish(&match_ticket,NULL); ++ } + /* ========== 根据命令类型决定变量更新时机 ========== */ + /* + * 持续监控型:只有 extract_pattern,无 expect/fail/stop_on_match +@@ -1707,58 +1480,58 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + * 结果导向型:有 expect/fail 或 stop_on_match + * → 等命令结束时才更新变量(在 ssh_exec_task 完成处理) + */ +- bool is_continuous_mode = s_exec_params->extract_pattern && +- !s_exec_params->expect_pattern && +- !s_exec_params->fail_pattern && +- !s_exec_params->stop_on_match; ++ bool is_continuous_mode = params->extract_pattern && ++ !params->expect_pattern && ++ !params->fail_pattern && ++ !params->stop_on_match; + + TS_LOGI(TAG, "Variable update check: var_name='%s', continuous=%d, extract=%p, expect=%p, fail=%p, stop=%d", +- s_exec_params->var_name, ++ params->var_name, + is_continuous_mode, +- s_exec_params->extract_pattern, +- s_exec_params->expect_pattern, +- s_exec_params->fail_pattern, +- s_exec_params->stop_on_match); ++ params->extract_pattern, ++ params->expect_pattern, ++ params->fail_pattern, ++ params->stop_on_match); + +- if (is_continuous_mode && s_exec_params->var_name[0]) { ++ if (is_continuous_mode && params->var_name[0]) { + /* 持续监控模式:实时更新变量 */ + char full_var_name[96]; + ts_auto_variable_t var = {0}; +- strncpy(var.source_id, s_exec_params->var_name, sizeof(var.source_id) - 1); ++ strncpy(var.source_id, params->var_name, sizeof(var.source_id) - 1); + var.flags = 0; + + /* 更新 extracted 变量 */ +- if (s_exec_params->extracted_value) { +- snprintf(full_var_name, sizeof(full_var_name), "%s.extracted", s_exec_params->var_name); ++ if (params->extracted_value) { ++ snprintf(full_var_name, sizeof(full_var_name), "%s.extracted", params->var_name); + strncpy(var.name, full_var_name, sizeof(var.name) - 1); + var.value.type = TS_AUTO_VAL_STRING; +- strncpy(var.value.str_val, s_exec_params->extracted_value, sizeof(var.value.str_val) - 1); ++ strncpy(var.value.str_val, params->extracted_value, sizeof(var.value.str_val) - 1); + esp_err_t ret = ts_variable_upsert(&var); +- TS_LOGI(TAG, "Registered %s = %s (ret=%d)", full_var_name, s_exec_params->extracted_value, ret); ++ TS_LOGI(TAG, "Registered %s = %s (ret=%d)", full_var_name, params->extracted_value, ret); + } + + /* 更新 status 为 running */ +- snprintf(full_var_name, sizeof(full_var_name), "%s.status", s_exec_params->var_name); ++ snprintf(full_var_name, sizeof(full_var_name), "%s.status", params->var_name); + strncpy(var.name, full_var_name, sizeof(var.name) - 1); + var.value.type = TS_AUTO_VAL_STRING; + strncpy(var.value.str_val, "running", sizeof(var.value.str_val) - 1); + ts_variable_upsert(&var); + + /* 更新 host */ +- snprintf(full_var_name, sizeof(full_var_name), "%s.host", s_exec_params->var_name); ++ snprintf(full_var_name, sizeof(full_var_name), "%s.host", params->var_name); + strncpy(var.name, full_var_name, sizeof(var.name) - 1); + var.value.type = TS_AUTO_VAL_STRING; +- strncpy(var.value.str_val, s_exec_params->config.host ? s_exec_params->config.host : "", sizeof(var.value.str_val) - 1); ++ strncpy(var.value.str_val, params->config.host ? params->config.host : "", sizeof(var.value.str_val) - 1); + ts_variable_upsert(&var); + + /* 更新 timestamp */ +- snprintf(full_var_name, sizeof(full_var_name), "%s.timestamp", s_exec_params->var_name); ++ snprintf(full_var_name, sizeof(full_var_name), "%s.timestamp", params->var_name); + strncpy(var.name, full_var_name, sizeof(var.name) - 1); + var.value.type = TS_AUTO_VAL_INT; + var.value.int_val = (int32_t)(esp_timer_get_time() / 1000000); + ts_variable_upsert(&var); + +- TS_LOGD(TAG, "Continuous mode: realtime update %s", s_exec_params->var_name); ++ TS_LOGD(TAG, "Continuous mode: realtime update %s", params->var_name); + } + /* 结果导向模式:变量在命令完成时更新(见下方 ssh_exec_task 完成处理) */ + +@@ -1766,55 +1539,74 @@ static void ssh_exec_output_callback(const char *data, size_t len, bool is_stder + if (should_stop) { + TS_LOGI(TAG, "Aborting SSH execution (pattern=%d, first_extract=%d)", + pattern_matched, is_first_extract); +- s_exec_cancel_requested = true; +- if (s_exec_session) { +- ts_ssh_abort(s_exec_session); /* 直接中断 SSH 执行 */ +- } ++ params->cancel_requested = true; ++ exec_abort(params); + } + } + } ++ ts_ws_op_release(params->op); + } + +-/* SSH Exec 超时回调 */ +-static void ssh_exec_timeout_callback(TimerHandle_t xTimer) ++/* Timer's original context is pinned from creation through the daemon barrier. ++ * The existing WS worker retries queue admission; it never waits on the daemon. */ ++static void ssh_exec_timeout_callback(TimerHandle_t timer) + { +- TS_LOGW(TAG, "SSH exec timeout triggered"); +- s_exec_cancel_requested = true; +- if (s_exec_session) { +- ts_ssh_abort(s_exec_session); ++ ssh_exec_task_params_t *params=pvTimerGetTimerID(timer); ++ xSemaphoreTake(params->io,portMAX_DELAY); ++ if(!params->timer_closing) { ++ params->cancel_requested=true; ++ if(params->session)ts_ssh_abort(params->session); + } ++ xSemaphoreGive(params->io); + } +- +-/* Every accepted streamed command owns one result reservation. Ordinary output +- * cannot consume it. Oversize/encoding failure is reported, never as success. */ +-static void ssh_exec_terminal_flush(void) ++static void exec_timer_drained(void *arg,uint32_t unused) ++{ ++ (void)unused;ssh_exec_task_params_t *params=arg; ++ params->timer_phase=5; ++ ts_ws_op_release(params->op); ++} ++static bool exec_maintenance(void *data) ++{ ++ ssh_exec_task_params_t *params=data;unsigned phase=params->timer_phase; ++ if(phase<2 || phase>=5)return false; ++ if(phase==4)return true; ++ if(esp_timer_get_time()timer_retry_at)return true; ++ BaseType_t ret=pdFAIL; ++ if(phase==2) { ++ ret=xTimerDelete(params->timer,0); ++ if(ret==pdPASS){params->timer=NULL;params->timer_phase=3;} ++ } else { ++ params->timer_phase=4; /* callback can finish before submit returns */ ++ ret=xTimerPendFunctionCall(exec_timer_drained,params,0,0); ++ if(ret!=pdPASS)params->timer_phase=3; ++ } ++ if(ret!=pdPASS)params->timer_retry_at=esp_timer_get_time()+100000; ++ if(ret!=pdPASS && ++params->timer_retries==TS_WS_QUEUE_RETRIES) { ++ params->timer_phase=phase==2?6:7; ++ TS_LOGE(TAG,"SSH timer drain retry limit; context retained until stop retry"); ++ return false; ++ } ++ if(ret==pdPASS)params->timer_retries=0; ++ return params->timer_phase!=5; ++} ++static void exec_retry_timer_drain(void) + { +- if(s_exec_output_pending)return; +- bool ready=true; +- if(!atomic_compare_exchange_strong(&s_exec_terminal_ready,&ready,false))return; +- if(s_exec_output_failed) { +- char fallback[224]; +- snprintf(fallback,sizeof(fallback),"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"SSH output delivery incomplete; remote command result is not confirmed\"}",(unsigned long)s_exec_session_id); +- ts_ws_reserved_text(&s_exec_terminal,fallback); +- } +- /* Completion owns the original recipient snapshot; never retarget on retry. */ +- esp_err_t ret=ts_ws_result_publish(&s_exec_terminal,s_exec_result_peers,s_exec_result_count); +- if(ret!=ESP_OK)TS_LOGW(TAG,"SSH terminal result rejected: %s",esp_err_to_name(ret)); +- ts_ws_reservation_release(&s_exec_terminal); +- s_exec_result_active=false; ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,0); ++ if(!op)return; ++ ssh_exec_task_params_t *params=ts_ws_op_data(op); ++ if(params){unsigned phase=params->timer_phase; ++ if(phase>=6){params->timer_retries=0;atomic_compare_exchange_strong(¶ms->timer_phase,&phase,phase==6?2:3);}} ++ ts_ws_op_release(op); + } +-static void ssh_exec_terminal_publish(const char *json,uint32_t session_id) ++static void exec_destroy(void *data) + { +- bool claimed=false; +- if(!atomic_compare_exchange_strong(&s_exec_terminal_claimed,&claimed,true))return; +- char fallback[192]; +- snprintf(fallback,sizeof(fallback),"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"SSH result delivery failed; result is unknown\"}",(unsigned long)session_id); +- esp_err_t ret=ts_ws_reserved_text(&s_exec_terminal,json?json:fallback); +- if(ret!=ESP_OK)ret=ts_ws_reserved_text(&s_exec_terminal,fallback); +- if(ret!=ESP_OK){TS_LOGW(TAG,"SSH terminal encoding failed: %s",esp_err_to_name(ret));ts_ws_reservation_release(&s_exec_terminal);s_exec_result_active=false;return;} +- s_exec_result_count=ts_ws_peer_snapshot(s_exec_result_peers,TS_WS_CONNECTIONS); +- s_exec_terminal_ready=true; +- ssh_exec_terminal_flush(); ++ ssh_exec_task_params_t *params=data;if(!params)return; ++ assert(!params->session && (!params->timer_phase || params->timer_phase==5)); ++ free((void*)params->config.host);free((void*)params->config.username); ++ if(params->password_owned){memset(params->password_owned,0,strlen(params->password_owned));free(params->password_owned);} ++ free(params->expect_pattern);free(params->fail_pattern);free(params->extract_pattern); ++ free(params->output_buffer);free(params->extracted_value); ++ vSemaphoreDelete(params->io);free(params); + } + + /* SSH Exec 任务 */ +@@ -1828,7 +1620,7 @@ static void ssh_exec_task(void *arg) + size_t key_len = 0; + + /* 重置取消请求标志 */ +- s_exec_cancel_requested = false; ++ /* Initialized by the creator before exposing the original context. */ + + TS_LOGI(TAG, "SSH exec task started: session_id=%lu, cmd=%s", + (unsigned long)session_id, params->command); +@@ -1845,65 +1637,82 @@ static void ssh_exec_task(void *arg) + } else { + TS_LOGE(TAG, "Failed to load key '%s': %s", params->keyid, esp_err_to_name(ret)); + /* 发送错误消息 */ +- cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", "ssh_exec_error"); +- cJSON_AddNumberToObject(msg, "session_id", session_id); +- cJSON_AddStringToObject(msg, "error", "Failed to load SSH key"); +- char *json = cJSON_PrintUnformatted(msg); ++ if(ts_ws_op_close_begin(params->op)) { ++ cJSON *msg = cJSON_CreateObject(); ++ bool encoded=msg!=NULL; ++ encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_error"))!=NULL && encoded; ++ encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; ++ encoded = (cJSON_AddStringToObject(msg, "error", "Failed to load SSH key"))!=NULL && encoded; ++ char *json = encoded?cJSON_PrintUnformatted(msg):NULL; + cJSON_Delete(msg); +- ssh_exec_terminal_publish(json,session_id); free(json); ++ ts_ws_op_close_finish(params->op,json); free(json); ++ } + goto cleanup; + } + } + + /* 创建 SSH 会话 */ +- ret = ts_ssh_session_create(¶ms->config, &s_exec_session); ++ ts_ssh_session_t created=NULL; ++ ret = ts_ssh_session_create(¶ms->config, &created); ++ xSemaphoreTake(params->io,portMAX_DELAY);params->session=created;xSemaphoreGive(params->io); + if (ret != ESP_OK) { + TS_LOGE(TAG, "Failed to create SSH session: %s", esp_err_to_name(ret)); ++ if(ts_ws_op_close_begin(params->op)) { + cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", "ssh_exec_error"); +- cJSON_AddNumberToObject(msg, "session_id", session_id); +- cJSON_AddStringToObject(msg, "error", "Failed to create SSH session"); +- char *json = cJSON_PrintUnformatted(msg); ++ bool encoded=msg!=NULL; ++ encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_error"))!=NULL && encoded; ++ encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; ++ encoded = (cJSON_AddStringToObject(msg, "error", "Failed to create SSH session"))!=NULL && encoded; ++ char *json = encoded?cJSON_PrintUnformatted(msg):NULL; + cJSON_Delete(msg); +- ssh_exec_terminal_publish(json,session_id); free(json); ++ ts_ws_op_close_finish(params->op,json); free(json); ++ } + goto cleanup; + } + + /* 连接 */ +- ret = ts_ssh_connect(s_exec_session); ++ ret = ts_ssh_connect(params->session); + if (ret != ESP_OK) { +- const char *err = ts_ssh_get_error(s_exec_session); ++ const char *err = ts_ssh_get_error(params->session); + TS_LOGE(TAG, "SSH connect failed: %s", err ? err : "unknown"); ++ if(ts_ws_op_close_begin(params->op)) { + cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", "ssh_exec_error"); +- cJSON_AddNumberToObject(msg, "session_id", session_id); +- cJSON_AddStringToObject(msg, "error", err ? err : "Connection failed"); +- char *json = cJSON_PrintUnformatted(msg); ++ bool encoded=msg!=NULL; ++ encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_error"))!=NULL && encoded; ++ encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; ++ encoded = (cJSON_AddStringToObject(msg, "error", err ? err : "Connection failed"))!=NULL && encoded; ++ char *json = encoded?cJSON_PrintUnformatted(msg):NULL; + cJSON_Delete(msg); +- ssh_exec_terminal_publish(json,session_id); free(json); ++ ts_ws_op_close_finish(params->op,json); free(json); ++ } + goto cleanup; + } + + /* 发送开始消息 */ + { ++ ts_ws_output_ticket_t start_ticket; ++ if(ts_ws_op_output_begin(params->op,&start_ticket)) { ++ if(start_ticket.count) { + cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", "ssh_exec_start"); +- cJSON_AddNumberToObject(msg, "session_id", session_id); +- cJSON_AddStringToObject(msg, "command", params->command); ++ bool encoded=msg!=NULL; ++ encoded = (cJSON_AddStringToObject(msg, "type", "ssh_exec_start"))!=NULL && encoded; ++ encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; ++ encoded = (cJSON_AddStringToObject(msg, "command", params->command))!=NULL && encoded; + /* 添加配置信息 */ + if (params->expect_pattern) { +- cJSON_AddStringToObject(msg, "expect_pattern", params->expect_pattern); ++ encoded = (cJSON_AddStringToObject(msg, "expect_pattern", params->expect_pattern))!=NULL && encoded; + } + if (params->fail_pattern) { +- cJSON_AddStringToObject(msg, "fail_pattern", params->fail_pattern); ++ encoded = (cJSON_AddStringToObject(msg, "fail_pattern", params->fail_pattern))!=NULL && encoded; + } + if (params->extract_pattern) { +- cJSON_AddStringToObject(msg, "extract_pattern", params->extract_pattern); ++ encoded = (cJSON_AddStringToObject(msg, "extract_pattern", params->extract_pattern))!=NULL && encoded; + } +- char *json = cJSON_PrintUnformatted(msg); ++ char *json = encoded?cJSON_PrintUnformatted(msg):NULL; + cJSON_Delete(msg); +- ssh_exec_stream_publish(json,session_id); free(json); ++ ts_ws_op_output_finish(&start_ticket,json); free(json); ++ } else ts_ws_op_output_finish(&start_ticket,NULL); ++ } + } + + /* 判断是否需要启动超时定时器 */ +@@ -1921,40 +1730,27 @@ static void ssh_exec_task(void *arg) + (unsigned long)params->timeout_ms, need_timeout, params->stop_on_match); + + if (need_timeout && params->timeout_ms > 0) { +- /* 创建或重置超时定时器 */ +- if (s_exec_timeout_timer == NULL) { +- s_exec_timeout_timer = xTimerCreate("ssh_timeout", +- pdMS_TO_TICKS(params->timeout_ms), +- pdFALSE, /* 单次触发 */ +- NULL, +- ssh_exec_timeout_callback); +- } else { +- /* 更新超时时间 */ +- xTimerChangePeriod(s_exec_timeout_timer, pdMS_TO_TICKS(params->timeout_ms), 0); +- } +- +- if (s_exec_timeout_timer) { +- xTimerStart(s_exec_timeout_timer, 0); +- TS_LOGI(TAG, "SSH exec timeout timer started: %lu ms", (unsigned long)params->timeout_ms); +- } ++ ts_ws_op_retain(params->op); ++ params->timer=xTimerCreate("ssh_timeout",pdMS_TO_TICKS(params->timeout_ms),pdFALSE,params,ssh_exec_timeout_callback); ++ if(params->timer){params->timer_phase=1; ++ if(xTimerStart(params->timer,0)!=pdPASS)TS_LOGW(TAG,"SSH timeout timer could not start"); ++ } else ts_ws_op_release(params->op); + } +- ++ + /* 流式执行命令 */ +- ret = ts_ssh_exec_stream(s_exec_session, params->command, ++ ret = ts_ssh_exec_stream(params->session, params->command, + ssh_exec_output_callback, +- (void *)(uintptr_t)session_id, ++ params, + &exit_code); + +- /* 停止超时定时器 */ +- if (s_exec_timeout_timer) { +- xTimerStop(s_exec_timeout_timer, 0); +- } +- ++ xSemaphoreTake(params->io,portMAX_DELAY);params->timer_closing=true;xSemaphoreGive(params->io); ++ if(params->timer_phase==1){params->timer_phase=2;ts_ws_subscriptions_wake();} ++ + /* 处理模式匹配和状态判断 */ + ts_webui_ssh_status_t status = TS_WEBUI_SSH_STATUS_SUCCESS; + + /* 检查是否因超时被取消 */ +- bool was_timeout = s_exec_cancel_requested && (ret == ESP_ERR_TIMEOUT); ++ bool was_timeout = params->cancel_requested && (ret == ESP_ERR_TIMEOUT); + + /* 优先使用实时匹配结果 */ + bool expect_matched = params->expect_matched; +@@ -2102,13 +1898,15 @@ static void ssh_exec_task(void *arg) + + /* 发送完成消息 */ + { ++ if(ts_ws_op_close_begin(params->op)) { + cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", +- status == TS_WEBUI_SSH_STATUS_CANCELLED ? "ssh_exec_cancelled" : "ssh_exec_done"); +- cJSON_AddNumberToObject(msg, "session_id", session_id); ++ bool encoded=msg!=NULL; ++ encoded = (cJSON_AddStringToObject(msg, "type", ++ status == TS_WEBUI_SSH_STATUS_CANCELLED ? "ssh_exec_cancelled" : "ssh_exec_done"))!=NULL && encoded; ++ encoded = (cJSON_AddNumberToObject(msg, "session_id", session_id))!=NULL && encoded; + + if (status != TS_WEBUI_SSH_STATUS_CANCELLED) { +- cJSON_AddNumberToObject(msg, "exit_code", exit_code); ++ encoded = (cJSON_AddNumberToObject(msg, "exit_code", exit_code))!=NULL && encoded; + + /* 状态字符串 */ + const char *status_str = "unknown"; +@@ -2120,35 +1918,36 @@ static void ssh_exec_task(void *arg) + case TS_WEBUI_SSH_STATUS_MATCH_FAILED: status_str = "match_failed"; break; + default: break; + } +- cJSON_AddStringToObject(msg, "status", status_str); ++ encoded = (cJSON_AddStringToObject(msg, "status", status_str))!=NULL && encoded; + + /* 简单的成功标志 */ + bool is_success = (status == TS_WEBUI_SSH_STATUS_SUCCESS || + status == TS_WEBUI_SSH_STATUS_MATCH_SUCCESS); +- cJSON_AddBoolToObject(msg, "success", is_success); ++ encoded = (cJSON_AddBoolToObject(msg, "success", is_success))!=NULL && encoded; + + /* 模式匹配结果 */ + if (params->expect_pattern) { +- cJSON_AddBoolToObject(msg, "expect_matched", expect_matched); ++ encoded = (cJSON_AddBoolToObject(msg, "expect_matched", expect_matched))!=NULL && encoded; + } + if (params->fail_pattern) { +- cJSON_AddBoolToObject(msg, "fail_matched", fail_matched); ++ encoded = (cJSON_AddBoolToObject(msg, "fail_matched", fail_matched))!=NULL && encoded; + } + + /* 提取的值 */ + if (extracted_value) { +- cJSON_AddStringToObject(msg, "extracted", extracted_value); ++ encoded = (cJSON_AddStringToObject(msg, "extracted", extracted_value))!=NULL && encoded; + } + + /* 错误信息 */ + if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) { +- cJSON_AddStringToObject(msg, "error", ts_ssh_get_error(s_exec_session)); ++ encoded = (cJSON_AddStringToObject(msg, "error", ts_ssh_get_error(params->session)))!=NULL && encoded; + } + } + +- char *json = cJSON_PrintUnformatted(msg); ++ char *json = encoded?cJSON_PrintUnformatted(msg):NULL; + cJSON_Delete(msg); +- ssh_exec_terminal_publish(json,session_id); free(json); ++ ts_ws_op_close_finish(params->op,json); free(json); ++ } + } + + /* 释放提取的值 */ +@@ -2163,148 +1962,19 @@ cleanup: + free(key_buf); + } + +- /* 断开并销毁会话 */ +- if (s_exec_session) { +- ts_ssh_disconnect(s_exec_session); +- ts_ssh_session_destroy(s_exec_session); +- s_exec_session = NULL; +- } +- +- /* 清理参数 */ +- if (params) { +- free(params->expect_pattern); +- free(params->fail_pattern); +- free(params->extract_pattern); +- free(params->output_buffer); +- free(params); +- } +- s_exec_params = NULL; +- +- s_exec_running = false; +- s_exec_task = NULL; +- ++ xSemaphoreTake(params->io,portMAX_DELAY); ++ params->timer_closing=true; ++ if(params->session){ts_ssh_disconnect(params->session);ts_ssh_session_destroy(params->session);params->session=NULL;} ++ xSemaphoreGive(params->io); ++ if(params->timer_phase==1)params->timer_phase=2; ++ ts_ws_op_executor_done(params->op); ++ + TS_LOGI(TAG, "SSH exec task ended: session_id=%lu", (unsigned long)session_id); + vTaskDelete(NULL); + } + +-static esp_err_t ts_webui_ssh_exec_start_impl(const char *host, uint16_t port, +- const char *user, const char *keyid, +- const char *password, const char *command, +- uint32_t *session_id) +-{ +- if (!host || !user || !command) { +- return ESP_ERR_INVALID_ARG; +- } +- +- /* 检查是否有正在运行的会话 */ +- if (s_exec_running) { +- TS_LOGW(TAG, "SSH exec session already running"); +- return ESP_ERR_INVALID_STATE; +- } +- +- /* 分配任务参数 */ +- ssh_exec_task_params_t *params = heap_caps_calloc(1, sizeof(ssh_exec_task_params_t), +- MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +- if (!params) params = calloc(1, sizeof(ssh_exec_task_params_t)); +- if (!params) { +- return ESP_ERR_NO_MEM; +- } +- +- /* 生成会话 ID */ +- s_exec_session_id++; +- if (s_exec_session_id == 0) s_exec_session_id = 1; /* 避免 0 */ +- +- /* 配置 SSH */ +- params->config = (ts_ssh_config_t)TS_SSH_DEFAULT_CONFIG(); +- params->config.host = strdup(host); +- params->config.port = port; +- params->config.username = strdup(user); +- params->config.timeout_ms = 30000; +- params->session_id = s_exec_session_id; +- +- /* 存储命令 */ +- strncpy(params->command, command, sizeof(params->command) - 1); +- +- /* 配置认证方式 */ +- if (keyid && keyid[0]) { +- strncpy(params->keyid, keyid, sizeof(params->keyid) - 1); +- /* 实际密钥加载在任务中完成 */ +- } else if (password && password[0]) { +- params->config.auth_method = TS_SSH_AUTH_PASSWORD; +- params->config.auth.password = strdup(password); +- } else { +- free((void *)params->config.host); +- free((void *)params->config.username); +- free(params); +- return ESP_ERR_INVALID_ARG; +- } +- +- /* 默认启用输出收集 */ +- params->collect_output = true; +- params->max_output_size = 64 * 1024; /* 默认 64KB */ +- +- /* 分配输出缓冲区 */ +- params->output_capacity = params->max_output_size; +- params->output_buffer = heap_caps_malloc(params->output_capacity, +- MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +- if (!params->output_buffer) { +- params->output_buffer = malloc(params->output_capacity); +- } +- if (params->output_buffer) { +- params->output_buffer[0] = '\0'; +- params->output_len = 0; +- } +- +- s_exec_running = true; +- s_exec_params = params; /* 设置全局指针供回调访问 */ +- +- /* 创建任务 - MUST use DRAM stack because keystore access requires NVS. +- * SPI Flash operations disable cache, and PSRAM access requires cache. +- */ +- BaseType_t ret = xTaskCreate(ssh_exec_task, "ssh_exec", 8192, params, 5, &s_exec_task); +- if (ret != pdPASS) { +- TS_LOGE(TAG, "Failed to create SSH exec task"); +- s_exec_running = false; +- s_exec_params = NULL; +- free((void *)params->config.host); +- free((void *)params->config.username); +- if (params->config.auth.password) free((void *)params->config.auth.password); +- free(params->output_buffer); +- free(params); +- return ESP_FAIL; +- } +- +- if (session_id) { +- *session_id = s_exec_session_id; +- } +- +- TS_LOGI(TAG, "SSH exec started: session_id=%lu, host=%s, cmd=%s", +- (unsigned long)s_exec_session_id, host, command); +- +- return ESP_OK; +-} +- +-esp_err_t ts_webui_ssh_exec_start(const char *host, uint16_t port, +- const char *user, const char *keyid, +- const char *password, const char *command, +- uint32_t *session_id) +-{ +- unsigned creators = atomic_fetch_add(&s_exec_creators, 1); +- esp_err_t ret=ESP_ERR_INVALID_STATE; +- if(!creators && !s_ws_stopping && !s_exec_running && !s_exec_result_active) { +- ret=ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal); +- if(ret==ESP_OK){s_exec_result_active=true;s_exec_output_failed=false;s_exec_terminal_ready=false;s_exec_terminal_claimed=false;} +- if(ret==ESP_OK) { +- ret=ts_webui_ssh_exec_start_impl(host, port, user, keyid, password, command, session_id); +- if(ret!=ESP_OK){ts_ws_reservation_release(&s_exec_terminal);s_exec_result_active=false;} +- } +- } +- atomic_fetch_sub(&s_exec_creators, 1); +- return ret; +-} +- + /* 带选项的扩展版本 */ +-static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port, ++static esp_err_t ts_webui_ssh_exec_start_ex_impl(ts_ws_operation_t *op, const char *host, uint16_t port, + const char *user, const char *keyid, + const char *password, const char *command, + const ts_webui_ssh_options_t *options, +@@ -2314,12 +1984,6 @@ static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port + return ESP_ERR_INVALID_ARG; + } + +- /* 检查是否有正在运行的会话 */ +- if (s_exec_running) { +- TS_LOGW(TAG, "SSH exec session already running"); +- return ESP_ERR_INVALID_STATE; +- } +- + /* 分配任务参数 */ + ssh_exec_task_params_t *params = heap_caps_calloc(1, sizeof(ssh_exec_task_params_t), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +@@ -2328,17 +1992,19 @@ static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port + return ESP_ERR_NO_MEM; + } + +- /* 生成会话 ID */ +- s_exec_session_id++; +- if (s_exec_session_id == 0) s_exec_session_id = 1; +- ++ params->op=op;params->session_id=ts_ws_op_id(op); ++ params->io=xSemaphoreCreateMutex(); ++ if(!params->io){free(params);return ESP_ERR_NO_MEM;} ++ ts_ws_op_bind(op,params,exec_destroy); ++ ts_ws_op_set_maintenance(op,exec_maintenance); ++ + /* 配置 SSH */ + params->config = (ts_ssh_config_t)TS_SSH_DEFAULT_CONFIG(); + params->config.host = strdup(host); + params->config.port = port; + params->config.username = strdup(user); + params->config.timeout_ms = (options && options->timeout_ms > 0) ? options->timeout_ms : 30000; +- params->session_id = s_exec_session_id; ++ + + /* 存储命令 */ + strncpy(params->command, command, sizeof(params->command) - 1); +@@ -2348,14 +2014,14 @@ static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port + strncpy(params->keyid, keyid, sizeof(params->keyid) - 1); + } else if (password && password[0]) { + params->config.auth_method = TS_SSH_AUTH_PASSWORD; +- params->config.auth.password = strdup(password); ++ params->password_owned=strdup(password); ++ params->config.auth.password=params->password_owned; + } else { +- free((void *)params->config.host); +- free((void *)params->config.username); +- free(params); +- return ESP_ERR_INVALID_ARG; ++ return ESP_ERR_INVALID_ARG; /* operation destructor owns partially built params */ + } +- ++ if(!params->config.host || !params->config.username || ++ (password && password[0] && !params->keyid[0] && !params->password_owned))return ESP_ERR_NO_MEM; ++ + /* 配置可选参数 */ + if (options) { + if (options->expect_pattern && options->expect_pattern[0]) { +@@ -2409,8 +2075,7 @@ static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port + } + } + +- s_exec_running = true; +- s_exec_params = params; ++ + + /* 命令开始时初始化所有变量(重置旧值) */ + TS_LOGI(TAG, "Checking var_name for init: '%s' (len=%d)", +@@ -2480,28 +2145,22 @@ static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port + /* 创建任务 - MUST use DRAM stack because keystore access requires NVS. + * SPI Flash operations disable cache, and PSRAM access requires cache. + */ +- BaseType_t ret = xTaskCreate(ssh_exec_task, "ssh_exec", 8192, params, 5, &s_exec_task); +- if (ret != pdPASS) { +- TS_LOGE(TAG, "Failed to create SSH exec task"); +- s_exec_running = false; +- s_exec_params = NULL; +- free((void *)params->config.host); +- free((void *)params->config.username); +- if (params->config.auth.password) free((void *)params->config.auth.password); +- free(params->expect_pattern); +- free(params->fail_pattern); +- free(params->extract_pattern); +- free(params->output_buffer); +- free(params); ++ /* Task may finish before task-create returns: creator still owns params. */ ++ ts_ws_op_executor_take(op); ++ ts_ws_op_open(op); ++ BaseType_t ret=xTaskCreate(ssh_exec_task,"ssh_exec",8192,params,5,NULL); ++ if(ret!=pdPASS){ ++ ts_ws_op_executor_done(op); ++ ts_ws_op_discard(op); + return ESP_FAIL; + } +- ++ + if (session_id) { +- *session_id = s_exec_session_id; ++ *session_id = params->session_id; + } + + TS_LOGI(TAG, "SSH exec started (extended): session_id=%lu, host=%s, cmd=%s, expect=%s", +- (unsigned long)s_exec_session_id, host, command, ++ (unsigned long)params->session_id, host, command, + params->expect_pattern ? params->expect_pattern : "(none)"); + + return ESP_OK; +@@ -2513,20 +2172,21 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, + const ts_webui_ssh_options_t *options, + uint32_t *session_id) + { +- unsigned creators = atomic_fetch_add(&s_exec_creators, 1); +- esp_err_t ret=ESP_ERR_INVALID_STATE; +- if(!creators && !s_ws_stopping && !s_exec_running && !s_exec_result_active) { +- ret=ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal); +- if(ret==ESP_OK){s_exec_result_active=true;s_exec_output_failed=false;s_exec_terminal_ready=false;s_exec_terminal_claimed=false;} +- if(ret==ESP_OK) { +- ret=ts_webui_ssh_exec_start_ex_impl(host, port, user, keyid, password, command, options, session_id); +- if(ret!=ESP_OK){ts_ws_reservation_release(&s_exec_terminal);s_exec_result_active=false;} +- } +- } +- atomic_fetch_sub(&s_exec_creators, 1); ++ esp_err_t admission; ++ ts_ws_operation_t *op=ts_ws_op_create(TS_WS_OP_EXEC,(ts_ws_peer_t){0},&admission); ++ if(!op)return admission; ++ esp_err_t ret=ts_webui_ssh_exec_start_ex_impl(op,host,port,user,keyid,password,command,options,session_id); ++ if(ret!=ESP_OK && ts_ws_op_starting(op))ts_ws_op_discard(op); ++ ts_ws_op_executor_done(op); + return ret; + } + ++esp_err_t ts_webui_ssh_exec_start(const char *host,uint16_t port,const char *user, ++ const char *keyid,const char *password,const char *command,uint32_t *session_id) ++{ ++ return ts_webui_ssh_exec_start_ex(host,port,user,keyid,password,command,NULL,session_id); ++} ++ + /* 释放结果结构 */ + void ts_webui_ssh_result_free(ts_webui_ssh_result_t *result) + { +@@ -2539,19 +2199,19 @@ void ts_webui_ssh_result_free(ts_webui_ssh_result_t *result) + + esp_err_t ts_webui_ssh_exec_cancel(uint32_t session_id) + { +- if (!s_exec_running || session_id != s_exec_session_id) { +- return ESP_ERR_INVALID_STATE; +- } +- +- if (s_exec_session) { +- ts_ssh_abort(s_exec_session); +- TS_LOGI(TAG, "SSH exec cancel requested: session_id=%lu", (unsigned long)session_id); +- } +- +- return ESP_OK; ++ if(!session_id)return ESP_ERR_INVALID_STATE; ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,session_id); ++ if(!op)return ESP_ERR_INVALID_STATE; ++ ssh_exec_task_params_t *params=ts_ws_op_data(op); ++ bool running=ts_ws_op_executing(op); ++ if(params && running)exec_abort(params); ++ ts_ws_op_release(op); ++ return running?ESP_OK:ESP_ERR_INVALID_STATE; + } + + bool ts_webui_ssh_exec_is_running(uint32_t session_id) + { +- return s_exec_running && (session_id == 0 || session_id == s_exec_session_id); ++ ts_ws_operation_t *op=ts_ws_op_acquire(TS_WS_OP_EXEC,session_id); ++ if(!op)return false; ++ bool running=ts_ws_op_executing(op);ts_ws_op_release(op);return running; + } +diff --git a/components/ts_webui/src/ts_ws_subscriptions.c b/components/ts_webui/src/ts_ws_subscriptions.c +index b9d9d6f..508a5d3 100644 +--- a/components/ts_webui/src/ts_ws_subscriptions.c ++++ b/components/ts_webui/src/ts_ws_subscriptions.c +@@ -1,6 +1,7 @@ + /** Demand-driven display telemetry. Hardware sampling/control is not scheduled here. */ + #include "ts_ws_subscriptions.h" + #include "ts_ws_transport.h" ++#include "ts_ws_operation.h" + #include "ts_api.h" + #include "ts_log.h" + #include "esp_timer.h" +@@ -196,6 +197,7 @@ static void collect_batch(target_t *targets, unsigned n, ts_ws_reservation_t *re + /* Called by the single worker; one bounded pass, no network wait under lock. */ + static void run_batch(void) + { ++ ts_ws_op_poll(); + ts_ws_transport_flush(); + target_t targets[MAX_SUBSCRIPTIONS]; + ts_ws_reservation_t reserved[8]={0}; +@@ -279,7 +281,7 @@ static TickType_t wait_ticks(int64_t delta) + static TickType_t next_wait(void) + { + if(ts_ws_transport_needs_flush()) return wait_ticks((int64_t)ts_ws_transport_retry_ms()*1000); +- int64_t now=esp_timer_get_time(), nearest=INT64_MAX; ++ int64_t now=esp_timer_get_time(), nearest=ts_ws_op_needs_tick()?esp_timer_get_time()+100000:INT64_MAX; + unsigned capacity=ts_ws_message_capacity() ? ts_ws_transport_capacity() : 0; + portENTER_CRITICAL(&s_lock); + for(unsigned i=0;i=r->count || r->slots[index]<0)return ESP_ERR_INVALID_ARG; ++ portENTER_CRITICAL(&s_lock);s_deliveries[r->slots[index]].peer=peer;portEXIT_CRITICAL(&s_lock); ++ return ts_ws_reserved_submit(r,index,revision,delivery,NULL,done); ++} +diff --git a/tests/ws_subscriptions/run_f1_f2.sh b/tests/ws_subscriptions/run_f1_f2.sh +index 564ae53..7c0b664 100644 +--- a/tests/ws_subscriptions/run_f1_f2.sh ++++ b/tests/ws_subscriptions/run_f1_f2.sh +@@ -12,9 +12,8 @@ for name,want in json.loads(Path('docs/repair/ws-f1-f2/baseline.json').read_text + assert hashlib.sha256((Path(sys.argv[1])/name).read_bytes()).hexdigest()==want,name + print('Frozen production snapshot hashes verified') + HASH +- # Current assertions/harness against unchanged frozen production sources. +- cp tests/ws_subscriptions/{test_f1_f2.c,test_reviewer.c,run_f1_f2.sh} "$build/tests/ws_subscriptions/" +- cp tests/ws_subscriptions/stubs/platform.h "$build/tests/ws_subscriptions/stubs/" ++ # Preserve the original harness that matches the historical production ABI. ++ tar -xzf docs/repair/ws-operation/baseline.tar.gz -C "$build" tests/ws_subscriptions/test_f1_f2.c tests/ws_subscriptions/test_reviewer.c tests/ws_subscriptions/run_f1_f2.sh tests/ws_subscriptions/stubs/platform.h + if bash "$build/tests/ws_subscriptions/run_f1_f2.sh" > "$build/red.txt" 2>&1; then + cat "$build/red.txt"; echo 'Unexpected baseline PASS'; exit 1 + fi +@@ -27,19 +26,7 @@ HASH + fi + export DEVELOPER_DIR=/Library/Developer/CommandLineTools + cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" +-python3 - "$build" <<'PY' +-from pathlib import Path +-import re,sys +-script=Path('tests/ws_subscriptions/run_reviewer.sh').read_text() +-code=script.split("<<'PY'\n",1)[1].split('\nPY',1)[0] +-exec(compile(code,'extract-reviewer','exec')) +-s=Path('components/ts_webui/src/ts_webui_ws.c').read_text();parts=[] +-for name in ['power_state_to_string','power_policy_event_handler','ts_webui_broadcast','simple_pattern_match','ssh_exec_output_callback']: +- m=re.search(r'^(?:static )?(?:const char \*|void |esp_err_t |bool )'+name+r'\([^;]*?\)\n\{',s,re.M);assert m,name +- parts.append(s[m.start():s.index('\n}',m.start())+2]) +-Path(sys.argv[1],'power_caller.inc').write_text('\n'.join(parts)) +-PY +-"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" -I"$build" tests/ws_subscriptions/test_f1_f2.c "$cjson/cJSON.c" -o "$build/f1f2" ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -Icomponents/ts_security/include -Icomponents/ts_automation/include -Icomponents/ts_drivers/include -Icomponents/ts_console/include -Icomponents/ts_net/include -Wno-macro-redefined -I"$cjson" -I"$build" tests/ws_subscriptions/test_f1_f2.c "$cjson/cJSON.c" -o "$build/f1f2" + failed=0 + scenarios="f1 f2" + if grep -q TS_WS_POWER_SLOTS components/ts_webui/include/ts_ws_transport.h; then scenarios="$scenarios late early identity exec continuous power_retry capacity retry_limit stop timeout class power_order fair"; fi +diff --git a/tests/ws_subscriptions/run_reviewer.sh b/tests/ws_subscriptions/run_reviewer.sh +index 90f3a47..200a1bf 100644 +--- a/tests/ws_subscriptions/run_reviewer.sh ++++ b/tests/ws_subscriptions/run_reviewer.sh +@@ -8,13 +8,6 @@ cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" + python3 - "$build" <<'PY' + from pathlib import Path + import sys,re +-s=Path('components/ts_webui/src/ts_webui_ws.c').read_text() +-names=['ts_webui_log_stream_enable','has_log_clients','update_log_stream_state','set_client_role','ssh_terminal_done','ssh_generation_valid','ssh_status_valid','ssh_request_error','ssh_send_status','ssh_output_done','ssh_terminal_flush','ssh_send_output','ssh_poll_task','ssh_cleanup','handle_ssh_connect','start_terminal_session','ts_webui_ws_stop','ssh_exec_output_done','ssh_exec_stream_publish','ssh_exec_terminal_flush','ssh_exec_terminal_publish','ws_handler'] +-parts=[] +-for name in names: +- m=re.search(r'^(?:static )?(?:esp_err_t|bool|void) '+name+r'\([^;]*?\)\n\{',s,re.M);assert m,name +- parts.append(s[m.start():s.index('\n}',m.start())+2]) +-Path(sys.argv[1],'reviewer_ws.inc').write_text('\n'.join(parts)) + for source,names,dest in [ + ('components/ts_net/src/ts_http_server.c',['http_handler_wrapper'],'reviewer_http.inc'), + ('main/ts_core_init.c',['core_release_components','core_init_rollback','ts_core_start','ts_core_stop','ts_core_deinit'],'reviewer_core.inc'), +@@ -25,7 +18,7 @@ for source,names,dest in [ + parts.append(s[m.start():s.index('\n}',m.start())+2]) + Path(sys.argv[1],dest).write_text('\n'.join(parts)) + PY +-cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer.c "$cjson/cJSON.c" -o "$build/reviewer" ++cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -Icomponents/ts_security/include -Icomponents/ts_automation/include -Icomponents/ts_drivers/include -Icomponents/ts_console/include -Icomponents/ts_net/include -Wno-macro-redefined -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer.c "$cjson/cJSON.c" -o "$build/reviewer" + "$build/reviewer" + + cc -std=gnu11 -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer_service.c -o "$build/service" +diff --git a/tests/ws_subscriptions/test_f1_f2.c b/tests/ws_subscriptions/test_f1_f2.c +index 94d83a8..2d77530 100644 +--- a/tests/ws_subscriptions/test_f1_f2.c ++++ b/tests/ws_subscriptions/test_f1_f2.c +@@ -1,94 +1,66 @@ +-#define WS_REVIEWER_NO_MAIN +-#include "test_reviewer.c" +-/* Actual power callback, with only the power status input type replaced. */ +-typedef enum {TS_POWER_POLICY_STATE_NORMAL,TS_POWER_POLICY_STATE_LOW_VOLTAGE,TS_POWER_POLICY_STATE_SHUTDOWN,TS_POWER_POLICY_STATE_PROTECTED,TS_POWER_POLICY_STATE_RECOVERY}ts_power_policy_state_t; +-enum {TS_POWER_POLICY_EVENT_STATE_CHANGED,TS_POWER_POLICY_EVENT_LOW_VOLTAGE,TS_POWER_POLICY_EVENT_COUNTDOWN_TICK,TS_POWER_POLICY_EVENT_SHUTDOWN_START,TS_POWER_POLICY_EVENT_PROTECTED,TS_POWER_POLICY_EVENT_RECOVERY_START,TS_POWER_POLICY_EVENT_RECOVERY_COMPLETE,TS_POWER_POLICY_EVENT_DEBUG_TICK}; +-typedef struct {ts_power_policy_state_t state;float current_voltage;unsigned countdown_remaining_sec,protection_count;}ts_power_policy_status_t; +-#include +-#include +-static struct {bool collect_output,match_found,fail_matched,expect_matched,stop_on_match;char *output_buffer,*fail_pattern,*expect_pattern,*extract_pattern,*extracted_value;size_t output_capacity,output_len;char var_name[64];ts_ssh_config_t config;} *s_exec_params; +-static bool s_exec_cancel_requested; +-static void *s_exec_session; +-typedef struct{char source_id[64],name[96];int flags;struct {int type;char str_val[256];int int_val;}value;}ts_auto_variable_t; +-#define TS_AUTO_VAL_STRING 1 +-#define TS_AUTO_VAL_INT 2 +-static int ts_variable_upsert(ts_auto_variable_t*v){(void)v;return 0;} +-static void ts_ssh_abort(void*s){(void)s;assert(!"network delivery must not abort remote commands");} +-#define malloc tracked_malloc +-#define heap_caps_malloc test_heap_malloc +-#define free tracked_free +-#include "power_caller.inc" +-#undef free +-#undef malloc +-#undef heap_caps_malloc +-static unsigned powers,errors; +-#ifdef TS_WS_POWER_SLOTS +-static unsigned outputs[32],terminals[32],logs,protection_order[64],protection_n; +-static void observe_all(httpd_ws_frame_t*f){observe_topic(f);const char*p=(const char*)f->payload;if(strstr(p,"power_event")){powers++;if(protection_n<64){cJSON*j=cJSON_Parse(p);protection_order[protection_n++]=cJSON_GetObjectItem(j,"protection_count")->valueint;cJSON_Delete(j);}}if(strstr(p,"ssh_exec_output")||strstr(p,"ssh_output"))outputs[sent_fd]++;if(strstr(p,"ssh_exec_error")||strstr(p,"\"status\":\"error\""))errors++;if(strstr(p,"ssh_exec_done")||strstr(p,"ssh_exec_error"))terminals[sent_fd]++;if(!strcmp(p,"log"))logs++;} +-static void exec_begin(void){s_exec_session_id++;s_exec_output_failed=false;s_exec_terminal_claimed=false;s_exec_terminal_ready=false;s_exec_result_active=true;assert(!s_exec_output_pending);assert(ts_ws_result_reserve(4096,&s_exec_terminal)==0);} +-#endif +-static void observe_power(httpd_ws_frame_t*f){if(strstr((char*)f->payload,"power_event"))powers++;if(strstr((char*)f->payload,"\"status\":\"error\""))errors++;} ++#define OP_ADAPTER_NO_MAIN ++#include "test_operation_adapter.c" ++static unsigned powers,errors,outputs[32],terminals[32],logs,protection_order[64],protection_n,observed_topics[8]; ++static void observe_all(httpd_ws_frame_t*f){const char*p=(char*)f->payload; ++ for(unsigned i=0;i<8;i++){char match[80];snprintf(match,sizeof(match),"\"topic\":\"%s\"",topics[i].name);if(strstr(p,match))observed_topics[i]++;} ++ if(strstr(p,"power_event")){powers++;if(protection_n<64){cJSON*j=cJSON_Parse(p);protection_order[protection_n++]=cJSON_GetObjectItem(j,"protection_count")->valueint;cJSON_Delete(j);}} ++ if(strstr(p,"ssh_exec_output")||strstr(p,"ssh_output"))outputs[sent_fd]++; ++ if(strstr(p,"ssh_exec_error")||strstr(p,"\"status\":\"error\""))errors++; ++ if(strstr(p,"ssh_exec_done")||strstr(p,"ssh_exec_error"))terminals[sent_fd]++; ++ if(!strcmp(p,"log"))logs++; ++} + static void power_change(void){ts_power_policy_status_t s={.state=TS_POWER_POLICY_STATE_PROTECTED,.current_voltage=10.0f,.protection_count=1};ts_event_t e={.id=TS_POWER_POLICY_EVENT_PROTECTED,.data=&s,.data_size=sizeof(s)};power_policy_event_handler(&e,NULL);} ++static void shell_end(void){ssh_cleanup();shell_task.fn(shell_task.arg);drive_all();} + int main(int argc,char**argv){ +- assert(argc==2);cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks);start();open_peer(1);sent_hook=observe_power; +- if(!strcmp(argv[1],"f1")){ +- connect_request(false,false);queue_fail=true;ssh_send_output("chunk",5);queue_fail=false;test_now+=100000;progress();pump(); +- bool handled=!s_ssh_running && errors>0; +- printf("F1 assertion: accepted SSH output enqueue failure reaches session and error frame: %s\n",handled?"PASS":"FAIL (stream still normal / no error frame)"); +- s_ssh_running=false;poll_exit();current=(void*)1;finish();return handled?0:1; ++ assert(argc==2);cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks);setup();close_peer(2);sent_hook=observe_all; ++ if(!strcmp(argv[1],"f1") || !strcmp(argv[1],"late") || !strcmp(argv[1],"early")){ ++ connect_shell();ssh_shell_context_t *ctx=shell_task.arg; ++ bool late=!strcmp(argv[1],"late"),early=!strcmp(argv[1],"early"); ++ if(late){ts_ws_message_t*m=ts_ws_message_text("block",5);assert(ts_ws_transport_submit(ts_ws_op_peer(ctx->op),m,0,0,NULL,NULL)==0);ts_ws_message_release(m);} ++ immediate=early;send_fail=early;queue_fail=!late&&!early;ssh_send_output(ctx,"chunk",5); ++ if(late){sdk_one();queue_fail=true;worker_step();} ++ queue_fail=send_fail=false;immediate=false;test_now+=100000;drive_all(); ++ assert(!ts_ws_op_is_open(ctx->op));if(!early)assert(errors==1); ++ shell_end();finish_ws();puts("PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe");return 0; + } + if(!strcmp(argv[1],"f2")){ + ts_ws_peer_t p;assert(ts_ws_peer_get((void*)11,1,&p));ts_ws_peer_log_level(p,5); + httpd_ws_frame_t f={.type=1,.payload=(uint8_t*)"log",.len=3};assert(ts_ws_transport_log(&f,1)==0);assert(ts_ws_transport_log(&f,1)==0); +- power_change();pump();bool handled=powers==1; +- printf("F2 assertion: protection transition survives ordinary log pool saturation: %s\n",handled?"PASS":"FAIL (no protection frame)");finish();return handled?0:1; +- } +-#ifdef TS_WS_POWER_SLOTS +- sent_hook=observe_all; +- if(!strcmp(argv[1],"late")){ +- connect_request(false,false); +- ts_ws_message_t*m=ts_ws_message_text("block",5);assert(ts_ws_transport_submit(s_ssh_peer,m,0,0,NULL,NULL)==0);ts_ws_message_release(m); +- ssh_send_output("out",3);assert(s_ssh_output_pending==1);ssh_send_status("closed","normal close");assert(s_ssh_terminal_ready && s_ssh_result_pending); +- sdk_one();queue_fail=true;worker_step();assert(s_ssh_output_failed && !s_ssh_output_pending);queue_fail=false;test_now+=100000;progress();pump(); +- assert(errors==1 && !strstr(payloads[1],"normal close"));s_ssh_running=false;poll_exit();current=(void*)1;finish(); +- puts("PASS late SSH rejection: prior output settles before terminal; closed becomes explicit incomplete-output error");return 0; +- } +- if(!strcmp(argv[1],"early")){ +- connect_request(false,false);immediate=true;uint64_t settled=s_tx_stats.settled; +- ssh_send_output("ok",2);assert(!s_ssh_output_pending && s_tx_stats.settled==settled+1 && outputs[1]==1); +- send_fail=true;ssh_send_output("fail",4);send_fail=false;immediate=false; +- assert(s_tx_stats.settled==settled+2 && s_ssh_output_failed && !s_ssh_running && !s_ssh_output_pending); +- poll_exit();current=(void*)1;finish();puts("PASS callback-before-return and actual send failure: exactly one settlement, no reference leak");return 0; ++ power_change();pump();assert(powers==1);finish_ws();puts("PASS F2: protection transition survives ordinary log saturation");return 0; + } + if(!strcmp(argv[1],"identity")){ +- connect_request(false,false);unsigned old=s_ssh_generation; +- ssh_send_output("old",3);close_peer(1);open_peer(1); +- connect_request(false,false);assert(s_ssh_generation==old); /* retained old producer blocks replacement */ +- pump();assert(s_ssh_output_failed && outputs[1]==0);poll_exit();current=(void*)1; +- connect_request(false,false);assert(s_ssh_generation>old && s_ssh_running); +- ssh_output_done(old,1,ESP_FAIL);assert(s_ssh_running && !s_ssh_output_failed); /* delayed old notification is fenced */ +- s_ssh_running=false;poll_exit();current=(void*)1;pump();finish();puts("PASS old connection/generation cannot receive old output or fail replacement session");return 0; ++ connect_shell();ssh_shell_context_t *ctx=shell_task.arg;unsigned id=ts_ws_op_id(ctx->op); ++ ssh_send_output(ctx,"old",3);close_peer(1);open_peer(1);assert(!ts_ws_op_create(TS_WS_OP_SHELL,*((ts_ws_peer_t*)reqs[1].sess_ctx),NULL)); ++ pump();assert(outputs[1]==0);shell_end();connect_shell();ctx=shell_task.arg;assert(ts_ws_op_id(ctx->op)>id); ++ settle_target(id,1,ESP_FAIL);assert(ts_ws_op_is_open(ctx->op));shell_end();finish_ws();puts("PASS original peer and operation identity isolation across reconnect");return 0; + } +- if(!strcmp(argv[1],"exec")){ +- open_peer(2);exec_begin();unsigned sid=s_exec_session_id;uint64_t settled_before=s_tx_stats.settled; +- ssh_exec_output_callback("part",4,false,(void*)(uintptr_t)sid);assert(s_exec_output_pending==2); +- ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\"}",sid);assert(s_exec_terminal_ready); +- sdk_one();assert(outputs[1]==1 && !terminals[1]);queue_fail=true;worker_step();queue_fail=false; +- assert(s_exec_output_failed && !s_exec_output_pending);test_now+=100000;worker_step();pump(); +- assert(outputs[1]==1 && outputs[2]==0 && terminals[1]==1 && terminals[2]==1 && errors==2);assert(s_tx_stats.settled==settled_before+4); +- assert(strstr(payloads[1],"not confirmed"));finish(); +- puts("PASS actual exec callback: partial target failure is independent; no successful output replay and no false done");return 0; ++ if(!strcmp(argv[1],"exec") || !strcmp(argv[1],"continuous")){ ++ bool partial=!strcmp(argv[1],"exec");if(partial)open_peer(2);uint32_t id; ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0);ssh_exec_task_params_t *params=exec_task.arg; ++ if(!partial)queue_fail=true; ++ ssh_exec_output_callback("part",4,false,params); ++ if(partial){if(ts_ws_op_close_begin(params->op))ts_ws_op_close_finish(params->op,"{\"type\":\"ssh_exec_done\"}");sdk_one();queue_fail=true;worker_step();} ++ queue_fail=false;test_now+=100000;drive_all();assert(terminals[1]==1);if(partial)assert(outputs[1]==1 && outputs[2]==0 && terminals[2]==1); ++ unsigned before=frames[1];size_t collected=params->output_len; ++ ssh_exec_output_callback("later",5,false,params);drive_all();assert(frames[1]==before && params->output_len==collected+5 && !aborts); ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",NULL)==ESP_ERR_INVALID_STATE); ++ exec_task.fn(exec_task.arg);finish_ws();assert(frames[1]==before);puts("PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay");return 0; + } +- if(!strcmp(argv[1],"continuous")){ +- exec_begin();queue_fail=true;ssh_exec_output_callback("chunk",5,false,(void*)(uintptr_t)s_exec_session_id);queue_fail=false; +- test_now+=100000;progress();pump();assert(errors==1 && !s_exec_output_pending && !s_exec_result_active); +- unsigned frames_before=frames[1];ssh_exec_output_callback("later",5,false,(void*)(uintptr_t)s_exec_session_id);ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\"}",s_exec_session_id);pump();assert(frames[1]==frames_before && !s_exec_cancel_requested); +- finish();puts("PASS continuous exec: observation reports incomplete immediately; no remote abort/replay or later normal completion");return 0; ++ if(!strcmp(argv[1],"class") || !strcmp(argv[1],"stop") || !strcmp(argv[1],"timeout")){ ++ connect_shell();ssh_shell_context_t *ctx=shell_task.arg;ssh_send_output(ctx,"last",4); ++ unsigned ordinary=0;for(unsigned i=TS_WS_TOPIC_TX_SLOTS;i0;assert(ordinary==1); ++ ts_ws_transport_cancel_topics();ts_ws_op_stats_t stats;ts_ws_op_stats(TS_WS_OP_SHELL,&stats);assert(stats.unsettled==1); ++ if(strcmp(argv[1],"class")){ ++ power_change();bool timeout=!strcmp(argv[1],"timeout");if(!timeout)delay_hook=progress; ++ assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);delay_hook=NULL;assert(s_worker && s_state==DRAINING); ++ for(unsigned i=0;i<12;i++)progress();assert(outputs[1]==1 && powers==1); ++ } ++ shell_end();finish_ws();puts("PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress");return 0; + } + if(!strcmp(argv[1],"power_retry")){ + open_peer(2);queue_fail=true;power_change();assert(s_tx_stats.power_accepted==1 && !powers); + worker_step();queue_fail=false;test_now+=100000;worker_step();sdk_one();worker_step();sdk_one();assert(powers==2); +- send_fail_fd=2;power_change();pump();send_fail_fd=-1;assert(powers==3 && s_tx_stats.power_failed==1);finish(); ++ send_fail_fd=2;power_change();pump();send_fail_fd=-1;assert(powers==3 && s_tx_stats.power_failed==1);finish_ws(); + puts("PASS protection queue recovery without new messages; partial socket failure never replays successful recipient");return 0; + } + if(!strcmp(argv[1],"capacity")){ +@@ -105,25 +77,14 @@ int main(int argc,char**argv){ + for(unsigned i=0;i=TS_WS_TOPIC_TX_SLOTS&&i0);}assert(powers>0&&logs>0);finish();puts("PASS bounded sustained log/protection/topic competition: all eligible classes progress");return 0; ++ pump();for(unsigned i=0;i<8;i++){printf("fair %s=%u\n",topics[i].name,observed_topics[i]);assert(observed_topics[i]>0);}assert(powers>0&&logs>0);finish_ws();puts("PASS bounded sustained log/protection/topic competition: all eligible classes progress");return 0; + } +-#endif + return 2; + } +diff --git a/tests/ws_subscriptions/test_init.c b/tests/ws_subscriptions/test_init.c +index 8de18f9..de7f708 100644 +--- a/tests/ws_subscriptions/test_init.c ++++ b/tests/ws_subscriptions/test_init.c +@@ -17,9 +17,10 @@ static ts_event_handler_handle_t s_power_event_handle; + static int fail_stage,mutex_calls; + static httpd_handle_t ts_http_server_get_handle(void){return fail_stage==1?NULL:(void*)11;} + static void peer_closed(ts_ws_peer_t peer){(void)peer;} ++static void ts_ws_op_enable(void){} + esp_err_t ts_ws_transport_start(httpd_handle_t server,ts_ws_closed_t fn){(void)server;(void)fn;return fail_stage==2?ESP_ERR_NO_MEM:ESP_OK;} + static int ts_ws_subscriptions_init(void){return fail_stage==3?ESP_ERR_NO_MEM:ESP_OK;} +-static esp_err_t ts_webui_ws_stop(httpd_handle_t server); ++static esp_err_t ts_webui_ws_stop(httpd_handle_t server){(void)server;return ESP_OK;} + static int manager_stop_result,barrier_result,tx_stop_result,tx_stop_calls; + static bool owner_context,s_exec_running,s_ssh_poll_alive,cleanup_finishes; + static atomic_bool s_exec_result_active,s_exec_output_failed,s_exec_terminal_ready; +@@ -56,18 +57,6 @@ static int register_event(const char*b,int id,void(*fn)(const ts_event_t*,void*) + #undef malloc + #undef heap_caps_malloc + #undef ts_event_register +-#include "ws_stop.inc" +- +-typedef struct {int unused;} ts_webui_ssh_options_t; +-esp_err_t ts_webui_ssh_exec_start(const char*,uint16_t,const char*,const char*,const char*,const char*,uint32_t*); +-static int creator_calls; +-static esp_err_t ts_webui_ssh_exec_start_impl(const char*h,uint16_t p,const char*u,const char*k,const char*w,const char*c,uint32_t*i){ +- (void)h;(void)p;(void)u;(void)k;(void)w;(void)c;(void)i;creator_calls++; +- assert(ts_webui_ssh_exec_start("fixture",22,"u",NULL,NULL,"fixture",NULL)==ESP_ERR_INVALID_STATE); +- return ESP_OK; +-} +-static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char*h,uint16_t p,const char*u,const char*k,const char*w,const char*c,const ts_webui_ssh_options_t*o,uint32_t*i){(void)o;return ts_webui_ssh_exec_start_impl(h,p,u,k,w,c,i);} +-#include "ws_creators.inc" + static void reset(void){ + if(s_terminal_mutex)vSemaphoreDelete(s_terminal_mutex);if(s_output_mutex)vSemaphoreDelete(s_output_mutex);free(s_terminal_output_buf); + s_terminal_mutex=s_output_mutex=NULL;s_terminal_output_buf=NULL;s_server=NULL;s_power_event_handle=NULL;mutex_calls=0;s_ws_stopping=false; +@@ -75,16 +64,5 @@ static void reset(void){ + int main(void){ + for(fail_stage=1;fail_stage<=8;fail_stage++){assert(ts_webui_ws_init()!=ESP_OK);reset();} + fail_stage=0;assert(ts_webui_ws_init()==0);assert(ts_webui_ws_init()==0);s_ws_stopping=true;assert(ts_webui_ws_init()==ESP_ERR_INVALID_STATE);reset(); +- manager_stop_result=ESP_ERR_TIMEOUT;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(!tx_stop_calls); +- manager_stop_result=0;barrier_result=ESP_ERR_TIMEOUT;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(!tx_stop_calls);barrier_result=0; +- s_exec_creators=1;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);s_exec_creators=0; +- s_exec_running=true;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);s_exec_running=false; +- s_ssh_poll_alive=true;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(!tx_stop_calls); +- cleanup_finishes=true;tx_stop_result=ESP_ERR_TIMEOUT;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);tx_stop_result=0;assert(ts_webui_ws_stop((void*)11)==0); +- owner_context=true;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE); +- puts("PASS actual WebSocket stop: manager/barrier failures propagate, active SSH creation/execution retained, poller timeout retained, transport drain retry and HTTPD self-wait rejected"); +- s_ws_stopping=false;assert(ts_webui_ssh_exec_start("fixture",22,"u",NULL,NULL,"fixture",NULL)==0);assert(creator_calls==1&&!s_exec_creators); +- s_ws_stopping=true;assert(ts_webui_ssh_exec_start("fixture",22,"u",NULL,NULL,"fixture",NULL)==ESP_ERR_INVALID_STATE);assert(creator_calls==1&&!s_exec_creators); +- puts("PASS actual SSH creation wrappers: concurrent builder rejected and stop admission closes without invoking the remote-operation implementation"); + puts("PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards"); + } +diff --git a/tests/ws_subscriptions/test_manager.c b/tests/ws_subscriptions/test_manager.c +index a881ab9..f433995 100644 +--- a/tests/ws_subscriptions/test_manager.c ++++ b/tests/ws_subscriptions/test_manager.c +@@ -18,6 +18,7 @@ static void test_point(const char *name); + #undef s_server + #undef s_sequence + #include "ts_ws_subscriptions.c" ++#include "ts_ws_operation.c" + #undef malloc + #undef free + static unsigned allocations, live_allocations; +diff --git a/tests/ws_subscriptions/test_reviewer.c b/tests/ws_subscriptions/test_reviewer.c +index a38c254..ac965e3 100644 +--- a/tests/ws_subscriptions/test_reviewer.c ++++ b/tests/ws_subscriptions/test_reviewer.c +@@ -1,160 +1,18 @@ +-/* Compose actual manager/transport with extracted, unmodified WebUI functions. */ +-#define main existing_manager_main +-#include "test_manager.c" +-#undef main +-#include +-#include +-#define MAX_WS_CLIENTS TS_WS_CONNECTIONS +-#define TS_LOG_NONE 0 +-#define TS_LOG_ERROR 1 +-#define TS_LOG_VERBOSE 5 +-#define HTTP_GET 0 +-#define HTTPD_WS_TYPE_CLOSE 8 +-#define CONFIG_TS_LOG_BUFFER_SIZE 16 +-#define SSH_OUTPUT_BUF_SIZE 4096 +-#define TS_SSH_AUTH_PASSWORD 1 +-typedef int ts_log_level_t; +-typedef enum {WS_CLIENT_TYPE_EVENT,WS_CLIENT_TYPE_TERMINAL,WS_CLIENT_TYPE_SSH_SHELL,WS_CLIENT_TYPE_LOG} ws_client_type_t; +-static struct {bool active;int fd;httpd_handle_t hd;ws_client_type_t type;int log_min_level;}s_clients[MAX_WS_CLIENTS]; +-static httpd_handle_t s_server=(void*)11; +-static bool s_ws_stopping,s_exec_running; +-static atomic_bool s_exec_terminal_claimed; +-static atomic_uint s_exec_creators; +-static ts_event_handler_handle_t s_power_event_handle; +-static ts_ws_peer_t s_ssh_peer; +-static int s_ssh_client_fd=-1,s_terminal_client_fd=-1; +-static void *s_ssh_session,*s_ssh_shell; +-static atomic_bool s_ssh_running,s_ssh_poll_alive; +-enum {SSH_IDLE,SSH_STARTING,SSH_READY,SSH_TERMINAL}; +-static atomic_uint s_ssh_state,s_ssh_generation,s_ssh_result_pending; +-static ts_ws_reservation_t s_ssh_terminal,s_exec_terminal; +-static atomic_uint s_ssh_output_pending,s_exec_output_pending; +-static atomic_bool s_ssh_output_failed,s_exec_output_failed,s_ssh_terminal_ready,s_exec_terminal_ready,s_exec_result_active; +-static unsigned s_exec_session_id; +-static ts_ws_peer_t s_exec_result_peers[TS_WS_CONNECTIONS]; +-static unsigned s_exec_result_count; +-static void ssh_terminal_flush(void); +-static void ssh_exec_terminal_flush(void); +-static void ssh_exec_terminal_publish(const char*,uint32_t); +-static bool shell_active,create_fails,close_on_create; +-static void update_log_stream_state(void); +-static bool has_log_clients(void); +-static int ts_webui_log_stream_enable(bool enabled); +-static void*s_log_callback_handle; +-static atomic_bool s_log_streaming_enabled; +-static int remove_log_result; +-static const char *incoming; +-static unsigned commands; +-static const char*s_level_names[]={"NONE","ERROR","WARN","INFO","DEBUG","VERBOSE"}; +-typedef struct{int timestamp_ms,level;const char*tag,*message,*task_name;}ts_log_entry_t; +-static void log_ws_callback(const ts_log_entry_t*e,void*u){(void)e;(void)u;} +-static int ts_log_add_callback(void(*fn)(const ts_log_entry_t*,void*),int level,void*u,void**h){(void)fn;(void)level;(void)u;*h=(void*)1;return 0;} +-static int ts_log_remove_callback(void*h){(void)h;return remove_log_result;} +-static size_t ts_log_buffer_search(ts_log_entry_t*e,size_t n,int a,int b,void*t,void*m){(void)e;(void)n;(void)a;(void)b;(void)t;(void)m;return 0;} +-static void*test_heap_malloc(size_t n,unsigned caps){(void)caps;return tracked_malloc(n);} +-static int add_client(httpd_req_t*r,ws_client_type_t t){(void)r;(void)t;commands++;return 0;} +-static int httpd_ws_recv_frame(httpd_req_t*r,httpd_ws_frame_t*f,size_t n){(void)r;f->type=HTTPD_WS_TYPE_TEXT;f->len=strlen(incoming);if(n)memcpy(f->payload,incoming,f->len);return 0;} +-static void handle_terminal_command(httpd_req_t*r,const char*d){(void)r;(void)d;commands++;} +-static void ts_console_request_interrupt(void){commands++;} +-static void handle_ssh_input(const char*d){(void)d;commands++;} +-static void handle_ssh_disconnect(void){commands++;} +-static void handle_ssh_signal(const char*s){(void)s;commands++;} +-static void handle_ssh_resize(int w,int h){(void)w;(void)h;commands++;} +-static int httpd_ws_send_frame(httpd_req_t*r,httpd_ws_frame_t*f){return httpd_ws_send_frame_async(r->handle,r->fd,f);} +-static void ts_console_clear_output_cb(void){} +-static void terminal_output_cb(const char*d,size_t n,void*u){(void)d;(void)n;(void)u;} +-static void ts_console_set_output_cb(void(*fn)(const char*,size_t,void*),void*u){(void)fn;(void)u;} +-static void cleanup_disconnected_client(int fd){(void)fd;} +-static void ssh_cleanup(void); +-static esp_err_t ssh_send_status(const char*,const char*); +-static void ssh_send_output(const char*d,size_t n); +-typedef struct {const char*host,*username;int port,auth_method,timeout_ms;struct {const char*password;}auth;}ts_ssh_config_t; +-typedef struct {int term_width,term_height,read_timeout_ms;}ts_shell_config_t; +-#define TS_SSH_DEFAULT_CONFIG() ((ts_ssh_config_t){0}) +-#define TS_SHELL_DEFAULT_CONFIG() ((ts_shell_config_t){0}) +-static int ts_ssh_session_create(const ts_ssh_config_t*c,void**out){(void)c;*out=(void*)5;return 0;} +-static int ts_ssh_connect(void*s){(void)s;return 0;} +-static const char*ts_ssh_get_error(void*s){(void)s;return "fixture";} +-static int ts_ssh_shell_open(void*s,const ts_shell_config_t*c,void**out){(void)s;(void)c;*out=(void*)6;shell_active=true;return 0;} +-static bool ts_ssh_shell_is_active(void*s){return s && shell_active;} +-static int ts_ssh_shell_read(void*s,char*b,size_t n,size_t*out){(void)s;(void)b;(void)n;*out=0;return 0;} +-static void ts_ssh_shell_close(void*s){(void)s;shell_active=false;} +-static void ts_ssh_disconnect(void*s){(void)s;} +-static void ts_ssh_session_destroy(void*s){(void)s;} +-static int xTaskCreateWithCaps(void(*fn)(void*),const char*n,unsigned size,void*a,unsigned prio,void*out,unsigned caps){ +- (void)fn;(void)n;(void)size;(void)a;(void)prio;(void)out;(void)caps; +- if(close_on_create)shell_active=false; +- return create_fails?0:pdPASS; +-} +-#define free tracked_free +-#define malloc tracked_malloc +-#define heap_caps_malloc test_heap_malloc +-#include "reviewer_ws.inc" +-#undef free +-#undef malloc +-#undef heap_caps_malloc +-static jmp_buf worker_yield; +-static void yield_worker(void){longjmp(worker_yield,1);} +-static void worker_step(void){ +- wait_hook=yield_worker;current=(void*)2; +- if(!setjmp(worker_yield))worker_fn(NULL); +- current=(void*)1;wait_hook=NULL; +-} +-static void sdk_one(void){ +- if(!queued)return; +- current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(queue[0]));q.fn(q.arg);current=(void*)1; +-} +-static void progress(void){sdk_one();if(s_worker){if(s_state==STOPPING)worker_exit();else worker_step();}} +-static void poll_exit(void){current=(void*)4;ssh_poll_task(NULL);current=(void*)3;} +-static void finish(void){ +- s_exec_running=false;delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL; +- for(int i=0;i<32;i++)if(reqs[i].sess_ctx)close_peer(i); +- ts_ws_transport_stopped((void*)11);assert(!live_allocations); +- s_ws_stopping=false; +-} +-static void connect_request(bool fail,bool close_early){ +- create_fails=fail;close_on_create=close_early; +- cJSON*params=cJSON_Parse("{\"host\":\"fixture\",\"user\":\"fixture\"}"); +- current=(void*)3;delay_hook=poll_exit;handle_ssh_connect(&reqs[1],params);delay_hook=NULL;current=(void*)1;cJSON_Delete(params); +-} ++#define OP_ADAPTER_NO_MAIN ++#include "test_operation_adapter.c" + static unsigned observed_topics[8]; +-static void observe_topic(httpd_ws_frame_t*f){ +- for(unsigned i=0;i<8;i++){ +- char match[80];snprintf(match,sizeof(match),"\"topic\":\"%s\"",topics[i].name); +- if(strstr((const char*)f->payload,match))observed_topics[i]++; +- } +-} +- +-#ifndef WS_REVIEWER_NO_MAIN ++static void observe_topic(httpd_ws_frame_t*f){for(unsigned i=0;i<8;i++){char match[80];snprintf(match,sizeof(match),"\"topic\":\"%s\"",topics[i].name);if(strstr((char*)f->payload,match))observed_topics[i]++;}} + int main(void){ +- cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); +- start();open_peer(1);open_peer(2);s_exec_terminal_claimed=false;assert(ts_ws_result_reserve(4096,&s_exec_terminal)==0);s_exec_running=true;delay_hook=progress; +- assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);delay_hook=NULL; +- assert(s_worker && s_state==DRAINING); +- reqs[1].method=1;incoming="{\"type\":\"ping\"}";current=(void*)3; +- assert(ws_handler(&reqs[1])==0 && strstr(payloads[1],"pong")); +- incoming="{\"type\":\"terminal_input\",\"data\":\"new-command\"}"; +- assert(ws_handler(&reqs[1])==0 && !commands && strstr(payloads[1],"stopping"));current=(void*)1; +- unsigned a=frames[1],b=frames[2]; +- httpd_ws_frame_t result={.payload=(uint8_t*)"final-result",.len=12}; +- ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\",\"session_id\":1}",1); +- sdk_one();assert(!queued && ts_ws_transport_needs_flush()); +- worker_step();sdk_one();assert(frames[1]==a+1 && frames[2]==b+1); +- assert(!transport_server.outstanding);finish(); +- puts("PASS R1: busy stop retains real worker; final fanout drains with no new producer message"); +- start();open_peer(1);open_peer(2); +- assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT && s_worker && s_state==DRAINING); +- a=frames[1];b=frames[2];assert(ts_ws_transport_broadcast(&result)==0); +- for(unsigned i=0;i<4;i++){sdk_one();worker_step();} +- assert(frames[1]==a+1 && frames[2]==b+1);finish(); +- start();open_peer(1);open_peer(2);a=frames[1];b=frames[2]; +- assert(ts_ws_transport_broadcast(&result)==0);assert(ts_ws_subscriptions_pause()==0); +- assert(ts_ws_transport_stop((void*)11,1)==ESP_ERR_TIMEOUT && s_worker); +- sdk_one();worker_step();sdk_one();assert(frames[1]==a+1 && frames[2]==b+1);finish(); +- puts("PASS R1 timeout: handler-barrier and transport-drain failures retain worker; accepted fanout progresses before retry"); +- +- +- start();ts_ws_peer_t peer=open_peer(1); ++ cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks);unsigned a; ++ setup();uint32_t id;assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);delay_hook=NULL;assert(s_worker && s_state==DRAINING); ++ reqs[1].method=1;incoming="{\"type\":\"ping\"}";current=(void*)3;assert(ws_handler(&reqs[1])==0 && strstr(payloads[1],"pong")); ++ incoming="{\"type\":\"terminal_input\",\"data\":\"new-command\"}";assert(ws_handler(&reqs[1])==0 && strstr(payloads[1],"stopping"));current=(void*)1; ++ exec_task.fn(exec_task.arg);for(unsigned i=0;i<20;i++)progress();assert(!ts_ws_op_busy());finish_ws(); ++ puts("PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds"); ++ setup();assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT && s_worker);for(unsigned i=0;i<20;i++)progress();finish_ws(); ++ puts("PASS HTTPD barrier timeout retains worker and retry state"); ++ setup();ts_ws_peer_t peer;assert(ts_ws_peer_get((void*)11,1,&peer)); + s_clients[0].active=true;s_clients[0].fd=1;s_clients[0].hd=peer.server; + set_client_role(peer,WS_CLIENT_TYPE_LOG,5); + httpd_ws_frame_t log={.payload=(uint8_t*)"old-log",.len=7}; +@@ -165,46 +23,13 @@ int main(void){ + assert(ts_ws_transport_log(&log,3)==0);set_client_role(peer,WS_CLIENT_TYPE_EVENT,0);set_client_role(peer,WS_CLIENT_TYPE_LOG,5); + a=frames[1];pump();assert(frames[1]==a); /* old generation cannot revive */ + assert(ts_ws_transport_log(&log,3)==0);pump();assert(frames[1]==a+1); +- finish();s_terminal_client_fd=-1; ++ finish_ws();s_terminal_client_fd=-1; + assert(ts_webui_log_stream_enable(true)==0);remove_log_result=ESP_ERR_INVALID_STATE; + assert(ts_webui_log_stream_enable(false)==ESP_ERR_INVALID_STATE && s_log_callback_handle && !s_log_streaming_enabled); + assert(ts_webui_log_stream_enable(true)==0 && s_log_streaming_enabled);remove_log_result=0;assert(ts_webui_log_stream_enable(false)==0); + puts("PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA"); + +- start();peer=open_peer(1);s_clients[0].active=true;s_clients[0].fd=1;s_clients[0].hd=peer.server; +- /* Occupy both ordinary buffers; a rejected startup still has its result slot. */ +- ts_ws_message_t*m1=ts_ws_message_text("one",3),*m2=ts_ws_message_text("two",3);assert(m1&&m2); +- set_client_role(peer,WS_CLIENT_TYPE_LOG,5); +- connect_request(true,false);assert(s_clients[0].type!=WS_CLIENT_TYPE_LOG);assert(s_ssh_state==SSH_TERMINAL && !s_ssh_poll_alive && !s_ssh_session); +- unsigned generation=s_ssh_generation; +- connect_request(false,false);assert(s_ssh_generation==generation && strstr(payloads[1],"still pending")); +- ts_ws_message_release(m1);ts_ws_message_release(m2);pump();assert(strstr(payloads[1],"Failed to create SSH session")); +- connect_request(false,true);pump();assert(strstr(payloads[1],"closed during startup"));assert(!s_ssh_session); +- connect_request(false,false);assert(s_ssh_state==SSH_READY && strstr(payloads[1],"connected")); +- /* Queue a READY from a background caller, then close before it executes. */ +- assert(ssh_send_status("connected","late readiness")==0); +- unsigned old_generation=s_ssh_generation; +- queue_fail=true;assert(ssh_send_status("error","fixture failure")==0); +- sdk_one();worker_step();assert(!queued && ts_ws_transport_needs_flush());queue_fail=false; +- assert(!ssh_status_valid(old_generation,SSH_READY)); +- test_now+=100000;worker_step();pump();assert(strstr(payloads[1],"fixture failure")); +- current=(void*)3;delay_hook=poll_exit;ssh_cleanup();delay_hook=NULL;current=(void*)1; +- connect_request(false,false); +- ts_ws_message_t *full1=ts_ws_message_text("full1",5),*full2=ts_ws_message_text("full2",5);assert(full1&&full2); +- ssh_send_output("payload",7);assert(s_ssh_state==SSH_TERMINAL && !s_ssh_running); +- poll_exit();current=(void*)1;ts_ws_message_release(full1);ts_ws_message_release(full2);pump(); +- assert(strstr(payloads[1],"SSH output delivery incomplete") && !s_ssh_session && !s_ssh_poll_alive); +- finish(); +- puts("PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid"); +- +- start();open_peer(1);s_exec_terminal_claimed=false;assert(ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal)==0); +- m1=ts_ws_message_text("one",3);m2=ts_ws_message_text("two",3);assert(m1&&m2); +- open_peer(2);a=frames[1];b=frames[2]; +- ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\",\"session_id\":7}",7); +- ts_ws_message_release(m1);ts_ws_message_release(m2);pump();assert(frames[1]==a+1&&frames[2]==b+1);finish(); +- puts("PASS R2 exec: admitted result reservation survives ordinary saturation and preserves recipients at completion"); +- +- start();peer=open_peer(1);uint64_t serial[8];for(unsigned i=0;i<8;i++){serial[i]=s_stats.serialized[i];subscribe(peer,topics[i].name,10000);} ++ setup();assert(ts_ws_peer_get((void*)11,1,&peer));uint64_t serial[8];for(unsigned i=0;i<8;i++){serial[i]=s_stats.serialized[i];subscribe(peer,topics[i].name,10000);} + sent_hook=observe_topic; + for(unsigned cycle=0;cycle<100;cycle++) {test_now+=10000000;run_batch();pump();} + for(unsigned i=0;i<8;i++) { +@@ -223,10 +48,8 @@ int main(void){ + test_now+=10000000;before=total_reads();run_batch();assert(total_reads()==before); + ts_ws_reservation_release(&reserved);run_batch();pump();assert(total_reads()>before); + char*large=malloc(TS_WS_LEGACY_BYTES);memset(large,'x',TS_WS_LEGACY_BYTES); +- m1=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);m2=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-TS_WS_POWER_BUDGET-1);assert(m1&&m2);free(large); ++ ts_ws_message_t *m1=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);ts_ws_message_t *m2=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-TS_WS_POWER_BUDGET-1);assert(m1&&m2);free(large); + test_now+=10000000;before=total_reads();run_batch();assert(total_reads()==before); +- ts_ws_message_release(m1);ts_ws_message_release(m2);run_batch();pump();assert(total_reads()>before);finish(); ++ ts_ws_message_release(m1);ts_ws_message_release(m2);run_batch();pump();assert(total_reads()>before);finish_ws(); + puts("PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity"); + } +- +-#endif +diff --git a/components/ts_webui/include/ts_ws_operation.h b/components/ts_webui/include/ts_ws_operation.h +new file mode 100644 +index 0000000..a971437 +--- /dev/null ++++ b/components/ts_webui/include/ts_ws_operation.h +@@ -0,0 +1,47 @@ ++#pragma once ++/* Internal lifecycle; all returned operation pointers carry a reference. */ ++#include "ts_ws_transport.h" ++typedef enum { TS_WS_OP_SHELL, TS_WS_OP_EXEC, TS_WS_OP_KINDS } ts_ws_op_kind_t; ++typedef enum { OP_FREE, OP_STARTING, OP_OPEN, OP_CLOSING, OP_FINALIZING, ++ OP_TERMINAL_PENDING, OP_TERMINAL_SETTLED, OP_RECLAIMING } ts_ws_op_phase_t; ++typedef struct ts_ws_operation ts_ws_operation_t; ++typedef struct { ++ ts_ws_operation_t *op; ++ uint64_t sequence; /* single producer order within this operation */ ++ ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ unsigned count; ++} ts_ws_output_ticket_t; ++typedef struct { ++ ts_ws_op_phase_t phase; ++ uint64_t identity, tickets, finished, registered, settled, finalizers, duplicates; ++ unsigned refs, executors, preparing, unsettled, terminals; ++ bool failed; ++} ts_ws_op_stats_t; ++void ts_ws_op_enable(void); ++void ts_ws_op_stop_admission(void); ++bool ts_ws_op_busy(void); ++ts_ws_operation_t *ts_ws_op_create(ts_ws_op_kind_t kind, ts_ws_peer_t peer, esp_err_t *error); ++void ts_ws_op_bind(ts_ws_operation_t *op, void *data, void (*destroy)(void *)); ++void *ts_ws_op_data(ts_ws_operation_t *op); /* caller owns a reference */ ++uint32_t ts_ws_op_id(ts_ws_operation_t *op); ++ts_ws_operation_t *ts_ws_op_acquire(ts_ws_op_kind_t kind, uint32_t id); ++void ts_ws_op_retain(ts_ws_operation_t *op); ++void ts_ws_op_release(ts_ws_operation_t *op); ++void ts_ws_op_executor_take(ts_ws_operation_t *op); ++void ts_ws_op_executor_done(ts_ws_operation_t *op); ++bool ts_ws_op_executing(ts_ws_operation_t *op); ++bool ts_ws_op_open(ts_ws_operation_t *op); ++bool ts_ws_op_is_open(ts_ws_operation_t *op); ++bool ts_ws_op_starting(ts_ws_operation_t *op); ++ts_ws_peer_t ts_ws_op_peer(ts_ws_operation_t *op); ++void ts_ws_op_discard(ts_ws_operation_t *op); /* unaccepted creation */ ++bool ts_ws_op_output_begin(ts_ws_operation_t *op, ts_ws_output_ticket_t *ticket); ++void ts_ws_op_output_finish(ts_ws_output_ticket_t *ticket, const char *json); ++/* winner owns a close builder until close_finish, before any encoding */ ++bool ts_ws_op_close_begin(ts_ws_operation_t *op); ++void ts_ws_op_close_finish(ts_ws_operation_t *op, const char *json); ++void ts_ws_op_poll(void); /* existing subscription worker, no new task */ ++void ts_ws_op_stats(ts_ws_op_kind_t kind, ts_ws_op_stats_t *stats); ++ ++void ts_ws_op_set_maintenance(ts_ws_operation_t *op,bool (*maintain)(void *)); ++bool ts_ws_op_needs_tick(void); +diff --git a/components/ts_webui/src/ts_ws_operation.c b/components/ts_webui/src/ts_ws_operation.c +new file mode 100644 +index 0000000..1f8ee93 +--- /dev/null ++++ b/components/ts_webui/src/ts_ws_operation.c +@@ -0,0 +1,217 @@ ++#include "ts_ws_operation.h" ++#include "ts_ws_subscriptions.h" ++#include "freertos/FreeRTOS.h" ++#include ++#include ++#include ++ ++#define OP_OUTPUT_TARGETS (2 * TS_WS_CONNECTIONS) ++typedef struct { uint64_t id; bool active; } op_target_t; ++struct ts_ws_operation { ++ ts_ws_op_stats_t ledger; ++ ts_ws_op_kind_t kind; ++ bool initializing, builder; ++ ts_ws_peer_t peer, terminal_peers[TS_WS_CONNECTIONS]; ++ unsigned terminal_count; ++ ts_ws_reservation_t terminal; ++ op_target_t output[OP_OUTPUT_TARGETS], final[TS_WS_CONNECTIONS]; ++ void *data; ++ void (*destroy)(void *); ++ bool (*maintain)(void *); ++}; ++static portMUX_TYPE s_op_lock = portMUX_INITIALIZER_UNLOCKED; ++static ts_ws_operation_t s_ops[TS_WS_OP_KINDS]; ++static uint64_t s_op_sequence, s_op_delivery; ++static bool s_op_accepting, s_op_tick; ++#define OP_LOCK() portENTER_CRITICAL(&s_op_lock) ++#define OP_UNLOCK() portEXIT_CRITICAL(&s_op_lock) ++ ++void ts_ws_op_enable(void) { OP_LOCK(); s_op_accepting=true; OP_UNLOCK(); } ++void ts_ws_op_stop_admission(void) { OP_LOCK(); s_op_accepting=false; OP_UNLOCK(); } ++bool ts_ws_op_busy(void) { ++ OP_LOCK(); bool busy=false; ++ for(unsigned i=0;i=TS_WS_OP_KINDS)return NULL; ++ if(error)*error=ESP_ERR_INVALID_STATE; ++ OP_LOCK(); ts_ws_operation_t *op=&s_ops[kind]; ++ if(!s_op_accepting || op->ledger.phase!=OP_FREE || s_op_sequence==UINT32_MAX) { OP_UNLOCK(); return NULL; } ++ *op=(ts_ws_operation_t){.kind=kind,.peer=peer,.initializing=true, ++ .ledger={.phase=OP_STARTING,.identity=++s_op_sequence,.refs=1,.executors=1}}; ++ OP_UNLOCK(); ++ esp_err_t ret=kind==TS_WS_OP_SHELL ? ts_ws_reserve(&peer,1,true,4096,&op->terminal) : ++ ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&op->terminal); ++ OP_LOCK(); op->initializing=false; OP_UNLOCK(); ++ if(error)*error=ret; ++ if(ret!=ESP_OK) { ts_ws_op_discard(op); ts_ws_op_executor_done(op); return NULL; } ++ return op; ++} ++void ts_ws_op_bind(ts_ws_operation_t *op,void *data,void (*destroy)(void *)) { ++ OP_LOCK(); assert(op->ledger.phase==OP_STARTING && !op->data);op->data=data;op->destroy=destroy;OP_UNLOCK(); ++} ++void ts_ws_op_set_maintenance(ts_ws_operation_t *op,bool (*maintain)(void *)) {OP_LOCK();op->maintain=maintain;OP_UNLOCK();} ++bool ts_ws_op_needs_tick(void) {OP_LOCK();bool yes=s_op_tick;OP_UNLOCK();return yes;} ++void *ts_ws_op_data(ts_ws_operation_t *op) { OP_LOCK();void *p=op->data;OP_UNLOCK();return p; } ++uint32_t ts_ws_op_id(ts_ws_operation_t *op) { return (uint32_t)op->ledger.identity; } ++ts_ws_peer_t ts_ws_op_peer(ts_ws_operation_t *op) { return op->peer; } ++ts_ws_operation_t *ts_ws_op_acquire(ts_ws_op_kind_t kind,uint32_t id) { ++ OP_LOCK();ts_ws_operation_t *op=&s_ops[kind]; ++ if(op->initializing || op->ledger.phase==OP_FREE || op->ledger.phase==OP_RECLAIMING || (id && op->ledger.identity!=id))op=NULL; ++ else op->ledger.refs++; ++ OP_UNLOCK();return op; ++} ++void ts_ws_op_retain(ts_ws_operation_t *op) { OP_LOCK();assert(op->ledger.refs);op->ledger.refs++;OP_UNLOCK(); } ++void ts_ws_op_release(ts_ws_operation_t *op) { ++ OP_LOCK();assert(op->ledger.refs);op->ledger.refs--;OP_UNLOCK();ts_ws_subscriptions_wake(); ++} ++void ts_ws_op_executor_take(ts_ws_operation_t *op) { ++ OP_LOCK();assert(op->ledger.refs);op->ledger.refs++;op->ledger.executors++;OP_UNLOCK(); ++} ++void ts_ws_op_executor_done(ts_ws_operation_t *op) { ++ OP_LOCK();assert(op->ledger.executors && op->ledger.refs);op->ledger.executors--;op->ledger.refs--;OP_UNLOCK();ts_ws_subscriptions_wake(); ++} ++bool ts_ws_op_executing(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.executors!=0;OP_UNLOCK();return yes; } ++bool ts_ws_op_open(ts_ws_operation_t *op) { ++ OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;if(yes)op->ledger.phase=OP_OPEN;OP_UNLOCK();return yes; ++} ++bool ts_ws_op_is_open(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.phase==OP_OPEN;OP_UNLOCK();return yes; } ++bool ts_ws_op_starting(ts_ws_operation_t *op) { OP_LOCK();bool yes=op->ledger.phase==OP_STARTING;OP_UNLOCK();return yes; } ++void ts_ws_op_discard(ts_ws_operation_t *op) { ++ OP_LOCK();assert((op->ledger.phase==OP_STARTING || op->ledger.phase==OP_OPEN) && !op->ledger.preparing && !op->ledger.unsettled);op->ledger.phase=OP_FINALIZING;OP_UNLOCK(); ++ ts_ws_reservation_release(&op->terminal); ++ OP_LOCK();op->ledger.phase=OP_TERMINAL_SETTLED;OP_UNLOCK(); ++} ++/* Caller holds a ref. The winner takes a second ref for snapshot/encoding. */ ++static bool close_locked(ts_ws_operation_t *op) { ++ if(op->ledger.phase!=OP_OPEN && op->ledger.phase!=OP_STARTING)return false; ++ op->ledger.phase=OP_CLOSING;op->builder=true;op->ledger.refs++;return true; ++} ++static void close_snapshot(ts_ws_operation_t *op) { ++ if(op->kind==TS_WS_OP_SHELL){op->terminal_peers[0]=op->peer;op->terminal_count=1;} ++ else op->terminal_count=ts_ws_peer_snapshot(op->terminal_peers,TS_WS_CONNECTIONS); ++} ++bool ts_ws_op_close_begin(ts_ws_operation_t *op) { ++ OP_LOCK();bool winner=close_locked(op);OP_UNLOCK(); ++ if(winner){close_snapshot(op);TS_WS_TEST_POINT("B07");}return winner; ++} ++static void fallback(ts_ws_operation_t *op,char *text,size_t size,bool failed) { ++ const char *reason=failed ? "SSH output delivery incomplete; remote command result is not confirmed" : "SSH result delivery failed; result is unknown"; ++ if(op->kind==TS_WS_OP_SHELL && !failed)reason="SSH status delivery failed"; ++ if(op->kind==TS_WS_OP_SHELL)snprintf(text,size,"{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"%s\"}",reason); ++ else snprintf(text,size,"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"%s\"}",(unsigned long)ts_ws_op_id(op),reason); ++} ++void ts_ws_op_close_finish(ts_ws_operation_t *op,const char *json) { ++ char text[256];fallback(op,text,sizeof(text),false); ++ if(!json || ts_ws_reserved_text(&op->terminal,json)!=ESP_OK)ts_ws_reserved_text(&op->terminal,text); ++ OP_LOCK();assert(op->builder);op->builder=false;assert(op->ledger.refs);op->ledger.refs--;OP_UNLOCK();ts_ws_subscriptions_wake(); ++} ++static void fail_locked(ts_ws_operation_t *op,bool *winner) { ++ op->ledger.failed=true;*winner=close_locked(op); ++} ++static void settle_target(uint64_t identity,uint64_t token,esp_err_t result) { ++ ts_ws_operation_t *op=NULL;bool winner=false,terminal=false; ++ OP_LOCK(); ++ for(unsigned i=0;ioutput[i].active && op->output[i].id==token){record=&op->output[i];break;} ++ if(!record)for(unsigned i=0;ifinal[i].active && op->final[i].id==token){record=&op->final[i];terminal=true;break;} ++ } ++ if(!record){if(op)op->ledger.duplicates++;OP_UNLOCK();return;} ++ record->active=false; ++ if(terminal){assert(op->ledger.terminals);op->ledger.terminals--;} ++ else { ++ if(result!=ESP_OK)fail_locked(op,&winner); ++ assert(op->ledger.unsettled);op->ledger.unsettled--;op->ledger.settled++; ++ } ++ /* Target ref becomes the callback ref; not dropped at counter decrement. */ ++ OP_UNLOCK(); ++ if(winner){close_snapshot(op);ts_ws_op_close_finish(op,NULL);} ++ TS_WS_TEST_POINT("B06"); ++ ts_ws_op_release(op); /* final access: old callback cannot enter replacement */ ++} ++bool ts_ws_op_output_begin(ts_ws_operation_t *op,ts_ws_output_ticket_t *t) { ++ *t=(ts_ws_output_ticket_t){0};TS_WS_TEST_POINT("B01"); ++ OP_LOCK();bool ok=op->ledger.phase==OP_OPEN; ++ if(ok){op->ledger.preparing++;t->sequence=++op->ledger.tickets;op->ledger.refs++;t->op=op;}OP_UNLOCK(); ++ if(!ok)return false; ++ if(op->kind==TS_WS_OP_SHELL){t->peers[0]=op->peer;t->count=1;} ++ else t->count=ts_ws_peer_snapshot(t->peers,TS_WS_CONNECTIONS); ++ TS_WS_TEST_POINT("B02");return true; ++} ++void ts_ws_op_output_finish(ts_ws_output_ticket_t *t,const char *json) { ++ if(!t->op)return; ++ ts_ws_operation_t *op=t->op;ts_ws_message_t *m=NULL; ++ if(t->count && json)m=ts_ws_message_text(json,strlen(json)); ++ uint64_t tokens[TS_WS_CONNECTIONS]={0};bool winner=false,registered=false; ++ TS_WS_TEST_POINT("B03"); ++ OP_LOCK(); ++ unsigned available=0;for(unsigned i=0;ioutput[i].active; ++ if(t->count && (!m || availablecount || s_op_delivery>UINT64_MAX-t->count))fail_locked(op,&winner); ++ else { ++ for(unsigned i=0,j=0;icount;i++)if(!op->output[i].active){ ++ tokens[j++]=++s_op_delivery;op->output[i]=(op_target_t){s_op_delivery,true}; ++ } ++ op->ledger.unsettled+=t->count;op->ledger.registered+=t->count;op->ledger.refs+=t->count;registered=true; ++ } ++ OP_UNLOCK(); ++ if(winner){close_snapshot(op);ts_ws_op_close_finish(op,NULL);} ++ TS_WS_TEST_POINT("B04"); ++ if(registered)for(unsigned i=0;icount;i++) { ++ esp_err_t ret=ts_ws_transport_submit(t->peers[i],m,op->ledger.identity,tokens[i],NULL,settle_target); ++ if(ret!=ESP_OK)settle_target(op->ledger.identity,tokens[i],ret); ++ } ++ ts_ws_message_release(m); ++ OP_LOCK();assert(op->ledger.preparing);op->ledger.preparing--;op->ledger.finished++;OP_UNLOCK(); ++ t->op=NULL;ts_ws_op_release(op); /* entire publication, including early done */ ++} ++void ts_ws_op_poll(void) { ++ bool tick=false; ++ for(unsigned k=0;kmaintain && op->ledger.phase>=OP_OPEN && op->ledger.phaseledger.refs++; ++ OP_UNLOCK(); ++ if(maintain){tick |= op->maintain(op->data);OP_LOCK();assert(op->ledger.refs);op->ledger.refs--;OP_UNLOCK();} ++ OP_LOCK(); ++ if(op->ledger.phase==OP_CLOSING && !op->builder && !op->ledger.preparing && !op->ledger.unsettled) { ++ op->ledger.phase=OP_FINALIZING;op->ledger.refs++;op->ledger.finalizers++; ++ r=op->terminal;op->terminal=(ts_ws_reservation_t){0};finalize=true; ++ } ++ OP_UNLOCK(); ++ if(finalize) { ++ char text[256]; ++ if(op->ledger.failed){fallback(op,text,sizeof(text),true);ts_ws_reserved_text(&r,text);} ++ OP_LOCK(); ++ unsigned n=op->terminal_count; ++ if(s_op_delivery>UINT64_MAX-n)n=0; /* lifetime exhaustion: no token reuse */ ++ for(unsigned i=0;ifinal[i]=(op_target_t){tokens[i],true};} ++ op->ledger.terminals=n;op->ledger.refs+=n;op->ledger.phase=OP_TERMINAL_PENDING; ++ OP_UNLOCK(); ++ for(unsigned i=0;iterminal_peers[i],op->ledger.identity,tokens[i],settle_target); ++ if(ret!=ESP_OK)settle_target(op->ledger.identity,tokens[i],ret); ++ TS_WS_TEST_POINT("B08"); ++ } ++ ts_ws_reservation_release(&r);ts_ws_op_release(op); ++ } ++ OP_LOCK(); ++ if(op->ledger.phase==OP_TERMINAL_PENDING && !op->ledger.terminals)op->ledger.phase=OP_TERMINAL_SETTLED; ++ if(op->ledger.phase==OP_TERMINAL_SETTLED && !op->ledger.refs) { ++ assert(!op->ledger.executors && !op->ledger.preparing && !op->ledger.unsettled && !op->terminal.message); ++ op->ledger.phase=OP_RECLAIMING;retire=true; ++ } ++ OP_UNLOCK(); ++ if(retire) { ++ TS_WS_TEST_POINT("B10");if(op->destroy)op->destroy(op->data); ++ OP_LOCK();op->data=NULL;op->destroy=NULL;op->maintain=NULL;op->ledger.phase=OP_FREE;OP_UNLOCK(); ++ } ++ } ++ OP_LOCK();s_op_tick=tick;OP_UNLOCK(); ++} ++void ts_ws_op_stats(ts_ws_op_kind_t kind,ts_ws_op_stats_t *stats) {OP_LOCK();*stats=s_ops[kind].ledger;OP_UNLOCK();} +diff --git a/tests/ws_subscriptions/baseline_operation_adapter.c b/tests/ws_subscriptions/baseline_operation_adapter.c +new file mode 100644 +index 0000000..ce452be +--- /dev/null ++++ b/tests/ws_subscriptions/baseline_operation_adapter.c +@@ -0,0 +1,163 @@ ++/* Compile the entire production WS unit, its actual declarations/public types, ++ * controller, manager and TX. Only external platform/business boundaries fake. */ ++#define main manager_regressions ++#include "test_manager.c" ++#undef main ++#include "../../components/ts_webui/include/ts_webui.h" ++#include "../../components/ts_core/ts_log/include/ts_log.h" ++#undef TS_LOGD ++#undef TS_LOGI ++#undef TS_LOGW ++#undef TS_LOGE ++#define TS_LOGD(...) ((void)0) ++#define TS_LOGI(...) ((void)0) ++#define TS_LOGW(...) ((void)0) ++#define TS_LOGE(...) ((void)0) ++#include "ts_console.h" ++#include "ts_ssh_client.h" ++#include "ts_ssh_shell.h" ++#include "ts_variable.h" ++#define HTTP_GET 0 ++#define HTTP_POST 1 ++#define HTTP_PUT 2 ++#define HTTP_DELETE 3 ++#define HTTP_PATCH 4 ++#include "ts_http_server.h" ++#include "freertos/timers.h" ++#include ++#define HTTP_GET 0 ++#define HTTPD_WS_TYPE_CLOSE 8 ++#define CONFIG_TS_LOG_BUFFER_SIZE 16 ++#define TS_EVENT_BASE_POWER "power" ++#define TS_EVENT_ANY_ID -1 ++typedef struct {const char *uri;int method;esp_err_t (*handler)(httpd_req_t *);void *user_ctx;bool is_websocket,handle_ws_control_frames;} httpd_uri_t; ++static int httpd_register_uri_handler(httpd_handle_t h,const httpd_uri_t *u){(void)h;(void)u;return 0;} ++static int httpd_ws_send_frame(httpd_req_t *r,httpd_ws_frame_t *f){return httpd_ws_send_frame_async(r->handle,r->fd,f);} ++static const char *incoming; ++static int httpd_ws_recv_frame(httpd_req_t *r,httpd_ws_frame_t *f,size_t n){(void)r;if(!incoming)return ESP_FAIL;f->type=1;f->len=strlen(incoming);if(n)memcpy(f->payload,incoming,f->len);return 0;} ++static void *host_heap_malloc(size_t n,unsigned caps){(void)caps;return tracked_malloc(n);} ++static void *host_calloc(size_t n,size_t z){void *p=tracked_malloc(n*z);if(p)memset(p,0,n*z);return p;} ++static void *host_heap_calloc(size_t n,size_t z,unsigned caps){(void)caps;return host_calloc(n,z);} ++static char *host_strdup(const char *s){size_t n=strlen(s)+1;char *p=tracked_malloc(n);if(p)memcpy(p,s,n);return p;} ++static char *host_strndup(const char *s,size_t n){char *p=tracked_malloc(n+1);if(p){memcpy(p,s,n);p[n]=0;}return p;} ++static struct {void (*fn)(void *);void *arg;} shell_task,exec_task; ++static bool task_create_fail,close_during_create,inline_exec; ++static int adapter_create(void(*fn)(void*),const char *name,unsigned stack,void *arg,unsigned priority,TaskHandle_t *out){ ++ (void)stack;(void)priority;(void)out;if(task_create_fail)return 0; ++ if(!strcmp(name,"ssh_poll"))shell_task=(typeof(shell_task)){fn,arg};else exec_task=(typeof(exec_task)){fn,arg}; ++ if(inline_exec && !strcmp(name,"ssh_exec"))fn(arg); ++ return pdPASS; ++} ++static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,void *arg,unsigned p,TaskHandle_t *out,unsigned caps); ++static BaseType_t xTimerChangePeriod(TimerHandle_t t,TickType_t period,TickType_t wait){(void)t;(void)period;(void)wait;return pdPASS;} ++static BaseType_t xTimerStop(TimerHandle_t t,TickType_t wait){(void)t;(void)wait;return pdPASS;} ++#define malloc tracked_malloc ++#define calloc host_calloc ++#define free tracked_free ++#define strdup host_strdup ++#define strndup host_strndup ++#define heap_caps_malloc host_heap_malloc ++#define heap_caps_calloc host_heap_calloc ++#define xTaskCreate adapter_create ++#define xTaskCreateWithCaps adapter_create_caps ++#include "ts_webui_ws.c" ++#undef malloc ++#undef calloc ++#undef free ++#undef strdup ++#undef strndup ++#undef heap_caps_malloc ++#undef heap_caps_calloc ++#undef xTaskCreate ++#undef xTaskCreateWithCaps ++struct ts_ssh_session_s {bool aborted;}; ++struct ts_ssh_shell_s {bool active;}; ++static unsigned aborts,variable_writes,session_destroys; ++static int remote_failure; ++static void (*remote_hook)(void); ++static bool remote_timeout; ++static struct host_timer {void *id;void (*fn)(TimerHandle_t);bool active;} *host_timer; ++static struct {void (*fn)(void *,uint32_t);void *arg;uint32_t value;TimerHandle_t deleted;} timer_queue[16]; ++static unsigned timer_queued;static bool timer_queue_fail,timer_inline; ++TimerHandle_t xTimerCreate(const char*n,TickType_t t,BaseType_t repeat,void*id,void(*fn)(TimerHandle_t)){ ++ (void)n;(void)t;(void)repeat;host_timer=calloc(1,sizeof(*host_timer));host_timer->id=id;host_timer->fn=fn;return host_timer; ++} ++void *pvTimerGetTimerID(TimerHandle_t t){return t->id;} ++BaseType_t xTimerStart(TimerHandle_t t,TickType_t wait){(void)wait;t->active=true;return pdPASS;} ++BaseType_t xTimerDelete(TimerHandle_t t,TickType_t wait){(void)wait;if(timer_queue_fail)return pdFAIL;assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){.deleted=t};return pdPASS;} ++BaseType_t xTimerPendFunctionCall(void(*fn)(void*,uint32_t),void *arg,uint32_t v,TickType_t wait){ ++ (void)wait;if(timer_queue_fail)return pdFAIL; ++ if(timer_inline && !timer_queued){fn(arg,v);return pdPASS;} ++ assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){fn,arg,v,NULL};return pdPASS; ++} ++static void timer_pump(void){while(timer_queued){typeof(timer_queue[0]) q=timer_queue[0];memmove(timer_queue,timer_queue+1,--timer_queued*sizeof(*timer_queue));if(q.deleted){free(q.deleted);host_timer=NULL;}else q.fn(q.arg,q.value);}} ++esp_err_t ts_ssh_session_create(const ts_ssh_config_t*c,ts_ssh_session_t *out){(void)c;if(remote_failure==1)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));return *out?ESP_OK:ESP_ERR_NO_MEM;} ++esp_err_t ts_ssh_connect(ts_ssh_session_t s){(void)s;return remote_failure==2?ESP_FAIL:ESP_OK;} ++const char *ts_ssh_get_error(ts_ssh_session_t s){(void)s;return "fake network error";} ++esp_err_t ts_ssh_disconnect(ts_ssh_session_t s){(void)s;return ESP_OK;} ++esp_err_t ts_ssh_session_destroy(ts_ssh_session_t s){session_destroys++;tracked_free(s);return ESP_OK;} ++void ts_ssh_abort(ts_ssh_session_t s){s->aborted=true;aborts++;} ++esp_err_t ts_ssh_shell_open(ts_ssh_session_t s,const ts_shell_config_t*c,ts_ssh_shell_t *out){(void)s;(void)c;if(remote_failure==3)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));(*out)->active=true;return 0;} ++bool ts_ssh_shell_is_active(ts_ssh_shell_t s){return s&&s->active;} ++esp_err_t ts_ssh_shell_close(ts_ssh_shell_t s){tracked_free(s);return 0;} ++esp_err_t ts_ssh_shell_read(ts_ssh_shell_t s,char *b,size_t n,size_t *out){(void)b;(void)n;*out=0;s->active=false;return 0;} ++esp_err_t ts_ssh_shell_write(ts_ssh_shell_t s,const char *b,size_t n,size_t *out){(void)s;(void)b;(void)n;(void)out;return 0;} ++esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t s,uint16_t w,uint16_t h){(void)s;(void)w;(void)h;return 0;} ++esp_err_t ts_ssh_shell_send_signal(ts_ssh_shell_t s,const char *signal){(void)s;(void)signal;return 0;} ++esp_err_t ts_ssh_exec_stream(ts_ssh_session_t s,const char *command,ts_ssh_output_cb_t cb,void *arg,int *code){ ++ (void)command;if(remote_hook)remote_hook();if(remote_timeout && host_timer)host_timer->fn(host_timer); ++ cb("value=42\n",9,false,arg);*code=0;return s->aborted?ESP_ERR_TIMEOUT:ESP_OK; ++} ++esp_err_t ts_keystore_load_private_key(const char *id,char **out,size_t *n){(void)id;(void)out;(void)n;return ESP_FAIL;} ++esp_err_t ts_variable_upsert(const ts_auto_variable_t *v){(void)v;variable_writes++;return 0;} ++esp_err_t ts_console_exec(const char *cmd,ts_cmd_result_t *result){(void)cmd;memset(result,0,sizeof(*result));return 0;} ++esp_err_t ts_console_clear_output_cb(void){return 0;} ++esp_err_t ts_console_set_output_cb(ts_console_output_cb_t cb,void *arg){(void)cb;(void)arg;return 0;} ++void ts_console_request_interrupt(void){} ++esp_err_t ts_log_add_callback(ts_log_callback_t cb,ts_log_level_t l,void *arg,ts_log_callback_handle_t *out){(void)cb;(void)l;(void)arg;*out=(void*)1;return 0;} ++static int remove_log_result; ++esp_err_t ts_log_remove_callback(ts_log_callback_handle_t h){(void)h;return remove_log_result;} ++size_t ts_log_buffer_search(ts_log_entry_t *e,size_t n,ts_log_level_t min,ts_log_level_t max,const char *tag,const char *keyword){(void)e;(void)n;(void)min;(void)max;(void)tag;(void)keyword;return 0;} ++httpd_handle_t ts_http_server_get_handle(void){return (void*)11;} ++void ts_http_server_set_stop_hooks(esp_err_t(*stop)(httpd_handle_t),void(*stopped)(httpd_handle_t)){(void)stop;(void)stopped;} ++static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){(void)caps;if(close_during_create)s_ssh_shell->active=false;return adapter_create(fn,n,stack,arg,p,out);} ++static unsigned replacement,terminal_count,output_count;static bool terminal_first; ++static void observe_old(httpd_ws_frame_t *f){const char*p=(char*)f->payload;if(strstr(p,"ssh_exec_error")||strstr(p,"ssh_exec_done"))terminal_count++;if(strstr(p,"ssh_exec_output")){output_count++;if(terminal_count)terminal_first=true;}} ++static void connect_old(void){cJSON*j=cJSON_Parse("{\"host\":\"fake\",\"user\":\"fake\"}");current=(void*)3;handle_ssh_connect(&reqs[1],j);current=(void*)1;cJSON_Delete(j);} ++static void baseline_poll_exit(void){current=(void*)4;shell_task.fn(shell_task.arg);current=(void*)3;} ++static void baseline_open(int fd){current=(void*)3;reqs[fd]=(httpd_req_t){.handle=(void*)11,.fd=fd};assert(add_client(&reqs[fd],WS_CLIENT_TYPE_EVENT)==ESP_OK);current=(void*)1;} ++static void g1_old_window(void){delay_hook=baseline_poll_exit;close_peer(1);delay_hook=NULL;assert(!s_ssh_poll_alive);baseline_open(1);connect_old();replacement=s_ssh_generation;} ++static jmp_buf baseline_yield; ++static void baseline_wait(void){longjmp(baseline_yield,1);} ++static void g2_old_window(void){ ++ current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(*queue));q.fn(q.arg);current=(void*)1; ++ queue_fail=true;wait_hook=baseline_wait;current=(void*)2;if(!setjmp(baseline_yield))worker_fn(NULL);current=(void*)1;wait_hook=NULL; ++ queue_fail=false;test_now+=100000;pump();assert(s_exec_output_failed && terminal_count==1); ++} ++int main(int argc,char**argv){ ++ assert(argc==2);cJSON_Hooks h={tracked_malloc,tracked_free};cJSON_InitHooks(&h);start();s_server=(void*)11;transport_server.closed=peer_closed;baseline_open(1); ++ if(!strcmp(argv[1],"g1")){ ++ connect_old();unsigned old=s_ssh_generation;ts_ws_message_t*m=ts_ws_message_text("block",5); ++ assert(ts_ws_transport_submit(s_ssh_peer,m,0,0,NULL,NULL)==0);ts_ws_message_release(m); ++ ssh_send_output("old",3); /* poller returns; SDK admission is deferred to worker */ ++ current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(*queue));q.fn(q.arg);current=(void*)1; ++ barrier_name="G1";barrier_action=g1_old_window;queue_fail=true; ++ wait_hook=baseline_wait;current=(void*)2;if(!setjmp(baseline_yield))worker_fn(NULL);current=(void*)1;wait_hook=NULL; ++ queue_fail=false;test_now+=100000;pump();bool bad=replacement>old && s_ssh_state==SSH_TERMINAL; ++ printf("G1 complete production unit: replacement=%u old=%u replacement_corrupted=%d\n",replacement,old,bad); ++ s_ssh_running=false;shell_task.fn(shell_task.arg);pump();stop();assert(!live_allocations);return bad?1:0; ++ } ++ assert(!strcmp(argv[1],"g2"));uint32_t id; ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ sent_hook=observe_old; ++ ts_ws_peer_t peer=*(ts_ws_peer_t*)reqs[1].sess_ctx;ts_ws_message_t *m=ts_ws_message_text("block",5); ++ assert(ts_ws_transport_submit(peer,m,0,0,NULL,NULL)==0);ts_ws_message_release(m); ++ ssh_exec_output_callback("A",1,false,(void*)(uintptr_t)id); ++ barrier_name="G2";barrier_action=g2_old_window; ++ ssh_exec_output_callback("prepared",8,false,(void*)(uintptr_t)id);pump();bool bad=terminal_first; ++ printf("G2 complete production unit: terminal_before_late_output=%d\n",bad); ++ /* Baseline's separately known credential leak: track/free only after its real ++ * task cleanup. This does not replace any lifecycle code or affect assertion. */ ++ const char *host=s_exec_params->config.host,*user=s_exec_params->config.username,*password=s_exec_params->config.auth.password; ++ exec_task.fn(exec_task.arg);pump();tracked_free((void*)host);tracked_free((void*)user);tracked_free((void*)password);stop();assert(!live_allocations);return bad?1:0; ++} +diff --git a/tests/ws_subscriptions/replay_operation_baseline.py b/tests/ws_subscriptions/replay_operation_baseline.py +new file mode 100644 +index 0000000..b43d2c6 +--- /dev/null ++++ b/tests/ws_subscriptions/replay_operation_baseline.py +@@ -0,0 +1,42 @@ ++"""Replay frozen production translation units; only add scheduling barriers.""" ++from pathlib import Path ++import hashlib, json, os, shutil, subprocess, tarfile, tempfile ++root = Path(__file__).resolve().parents[2] ++os.chdir(root) ++sdk = os.environ.get('IDF_PATH') ++if not sdk: ++ raise SystemExit('NOT RUN: set IDF_PATH to the project SDK') ++for name,want in json.loads(Path('docs/repair/ws-operation/public-headers.json').read_text()).items(): ++ assert hashlib.sha256(Path(name).read_bytes()).hexdigest()==want,name ++with tempfile.TemporaryDirectory(prefix='ts-operation-baseline-') as tmp: ++ base = Path(tmp) ++ with tarfile.open('docs/repair/ws-operation/baseline.tar.gz') as archive: ++ archive.extractall(base) ++ for name, want in json.loads(Path('docs/repair/ws-operation/baseline.json').read_text())['sha256'].items(): ++ assert hashlib.sha256((base/name).read_bytes()).hexdigest() == want, name ++ print('Frozen production source and original tests SHA256 verified', flush=True) ++ source = base/'components/ts_webui/src/ts_webui_ws.c' ++ code = source.read_text() ++ for old, new in [ ++ ('atomic_fetch_sub(&s_ssh_output_pending,1);', 'atomic_fetch_sub(&s_ssh_output_pending,1); TS_WS_TEST_POINT("G1");'), ++ ('ts_ws_message_t *m=json?ts_ws_message_text(json,strlen(json)):NULL;', 'TS_WS_TEST_POINT("G2");\n ts_ws_message_t *m=json?ts_ws_message_text(json,strlen(json)):NULL;')]: ++ assert code.count(old) == 1 ++ code = code.replace(old, new) ++ source.write_text(code) ++ fixture = base/'tests/ws_subscriptions/baseline_operation_adapter.c' ++ shutil.copy(root/'tests/ws_subscriptions/baseline_operation_adapter.c', fixture) ++ shutil.copy(root/'tests/ws_subscriptions/stubs/esp_console.h', base/'tests/ws_subscriptions/stubs/esp_console.h') ++ shutil.copy(root/'tests/ws_subscriptions/stubs/freertos/timers.h', base/'tests/ws_subscriptions/stubs/freertos/timers.h') ++ # Public business headers are unchanged from HEAD; compile against their real declarations. ++ includes = [base/'tests/ws_subscriptions/stubs', base/'components/ts_webui/include', base/'components/ts_webui/src'] ++ includes += [root/'components'/p/'include' for p in ('ts_security','ts_automation','ts_drivers','ts_console','ts_net')] ++ cjson = Path(sdk)/'components/json/cJSON' ++ cmd = [os.environ.get('CC','cc'), '-std=gnu11','-g','-Wno-deprecated-declarations','-Wno-macro-redefined','-fsanitize=address,undefined'] ++ cmd += ['-I'+str(p) for p in includes+[cjson]] ++ cmd += [str(fixture), str(cjson/'cJSON.c'), '-o', str(base/'baseline')] ++ subprocess.run(cmd, check=True) ++ for case, expected in [('g1','replacement_corrupted=1'),('g2','terminal_before_late_output=1')]: ++ run = subprocess.run([str(base/'baseline'),case], capture_output=True, text=True) ++ print(run.stdout, end='', flush=True) ++ assert run.returncode == 1 and expected in run.stdout and not run.stderr, run.stderr ++ print('CONFIRMED G1/G2 are business assertion failures in the complete frozen WS unit, not compile/dependency/cleanup failures') +diff --git a/tests/ws_subscriptions/run_operation.sh b/tests/ws_subscriptions/run_operation.sh +new file mode 100644 +index 0000000..d1ab31b +--- /dev/null ++++ b/tests/ws_subscriptions/run_operation.sh +@@ -0,0 +1,9 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++: "${IDF_PATH:?NOT RUN: set IDF_PATH to the project SDK}" ++build=$(mktemp -d /tmp/ts-ws-operation.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++cjson="$IDF_PATH/components/json/cJSON" ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" tests/ws_subscriptions/test_operation.c "$cjson/cJSON.c" -o "$build/operation" ++"$build/operation" +diff --git a/tests/ws_subscriptions/run_operation_adapter.sh b/tests/ws_subscriptions/run_operation_adapter.sh +new file mode 100644 +index 0000000..e1edc6f +--- /dev/null ++++ b/tests/ws_subscriptions/run_operation_adapter.sh +@@ -0,0 +1,11 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++: "${IDF_PATH:?NOT RUN: set IDF_PATH to the project SDK}" ++build=$(mktemp -d /tmp/ts-ws-adapter.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++cjson="$IDF_PATH/components/json/cJSON" ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -Wno-macro-redefined -fsanitize=address,undefined \ ++ -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -Icomponents/ts_security/include -Icomponents/ts_automation/include -Icomponents/ts_drivers/include -Icomponents/ts_console/include -Icomponents/ts_net/include -I"$cjson" \ ++ tests/ws_subscriptions/test_operation_adapter.c "$cjson/cJSON.c" -o "$build/adapter" ++"$build/adapter" +diff --git a/tests/ws_subscriptions/stubs/esp_console.h b/tests/ws_subscriptions/stubs/esp_console.h +new file mode 100644 +index 0000000..93554c8 +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/esp_console.h +@@ -0,0 +1,2 @@ ++#pragma once ++typedef int (*esp_console_cmd_func_t)(int,char **); +diff --git a/tests/ws_subscriptions/stubs/freertos/timers.h b/tests/ws_subscriptions/stubs/freertos/timers.h +new file mode 100644 +index 0000000..8067a3d +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/freertos/timers.h +@@ -0,0 +1,12 @@ ++#pragma once ++#include "platform.h" ++typedef struct host_timer *TimerHandle_t; ++TimerHandle_t xTimerCreate(const char *,TickType_t,BaseType_t,void *,void (*)(TimerHandle_t)); ++void *pvTimerGetTimerID(TimerHandle_t); ++BaseType_t xTimerStart(TimerHandle_t,TickType_t); ++BaseType_t xTimerDelete(TimerHandle_t,TickType_t); ++BaseType_t xTimerPendFunctionCall(void (*)(void *,uint32_t),void *,uint32_t,TickType_t); ++#ifndef pdFALSE ++#define pdFALSE 0 ++#define pdFAIL 0 ++#endif +diff --git a/tests/ws_subscriptions/test_operation.c b/tests/ws_subscriptions/test_operation.c +new file mode 100644 +index 0000000..f177406 +--- /dev/null ++++ b/tests/ws_subscriptions/test_operation.c +@@ -0,0 +1,58 @@ ++#define main manager_regressions ++#include "test_manager.c" ++#undef main ++static ts_ws_operation_t *op; ++static ts_ws_op_kind_t kind; ++static unsigned destroys; ++static void destroy(void *p){(void)p;destroys++;} ++static void drive(void){for(unsigned i=0;i<8;i++){ts_ws_op_poll();pump();}} ++static void close_op(void){if(ts_ws_op_close_begin(op))ts_ws_op_close_finish(op,"{\"type\":\"done\"}");} ++static void inspect(void){ ++ ts_ws_op_stats_t s;ts_ws_op_stats(kind,&s); ++ assert(s.tickets==s.finished+s.preparing); ++ assert(s.registered==s.settled+s.unsettled); ++ assert(s.finalizers<=1); ++ if(s.phase==OP_FREE)assert(!s.refs && !s.executors && !s.preparing && !s.unsettled && !s.terminals); ++} ++static void close_during_prepare(void){close_op();ts_ws_op_poll();ts_ws_op_stats_t s;ts_ws_op_stats(kind,&s);assert(s.phase==OP_CLOSING && s.preparing==1);} ++static void try_replace(void){assert(!ts_ws_op_create(kind,ts_ws_op_peer(op),NULL));inspect();} ++static void old_failure_exit(void){ts_ws_op_executor_done(op);try_replace();ts_ws_op_poll();try_replace();} ++static void deny_ticket(void){close_op();ts_ws_op_stop_admission();} ++int main(void){ ++ cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); ++ const char *points[]={"B01","B02","B03","B04","B05","B06","B07","B08","B10"}; ++ for(kind=0;kind=1&&scenario<=3?close_during_prepare:scenario==5?old_failure_exit:try_replace; ++ ts_ws_output_ticket_t ticket; ++ bool accepted=ts_ws_op_output_begin(op,&ticket); ++ if(scenario==5)queue_fail=true; ++ if(accepted)ts_ws_op_output_finish(&ticket,"{\"type\":\"output\"}"); ++ queue_fail=false; ++ if(scenario!=5)close_op(); ++ drive();inspect(); ++ if(scenario!=5){ /* B09: settled observation cannot release business context */ ++ assert(ts_ws_op_executing(op));try_replace();ts_ws_output_ticket_t denied;assert(!ts_ws_op_output_begin(op,&denied)); ++ ts_ws_op_executor_done(op); ++ } ++ drive();inspect();assert(!ts_ws_op_busy());assert(!barrier_action); ++ immediate=false;stop();assert(!live_allocations); ++ } ++ for(kind=0;kindledger.identity,token=op->output[0].id; ++ close_op();drive();inspect();uint64_t settled=op->ledger.settled; ++ settle_target(identity,token,ESP_FAIL);settle_target(identity,token,ESP_OK); ++ assert(op->ledger.settled==settled && op->ledger.duplicates>=2);inspect(); ++ ts_ws_op_executor_done(op);drive();assert(!ts_ws_op_busy());stop();assert(!live_allocations); ++ } ++ puts("PASS 16 failure schedules: encode/SDK/socket/stale peer, early/deferred done, duplicate tokens do not double-settle"); ++ printf("PASS production operation/TX: 36 barrier schedules, ticket/target ledgers and B09 executor retention; destroyed=%u\n",destroys); ++ return 0; ++} +diff --git a/tests/ws_subscriptions/test_operation_adapter.c b/tests/ws_subscriptions/test_operation_adapter.c +new file mode 100644 +index 0000000..89d428b +--- /dev/null ++++ b/tests/ws_subscriptions/test_operation_adapter.c +@@ -0,0 +1,284 @@ ++/* Compile the entire production WS unit, its actual declarations/public types, ++ * controller, manager and TX. Only external platform/business boundaries fake. */ ++#define main manager_regressions ++#include "test_manager.c" ++#undef main ++#include "../../components/ts_webui/include/ts_webui.h" ++#include "../../components/ts_core/ts_log/include/ts_log.h" ++#undef TS_LOGD ++#undef TS_LOGI ++#undef TS_LOGW ++#undef TS_LOGE ++#define TS_LOGD(...) ((void)0) ++#define TS_LOGI(...) ((void)0) ++#define TS_LOGW(...) ((void)0) ++#define TS_LOGE(...) ((void)0) ++#include "ts_console.h" ++#include "ts_ssh_client.h" ++#include "ts_ssh_shell.h" ++#include "ts_variable.h" ++#define HTTP_GET 0 ++#define HTTP_POST 1 ++#define HTTP_PUT 2 ++#define HTTP_DELETE 3 ++#define HTTP_PATCH 4 ++#include "ts_http_server.h" ++#include "freertos/timers.h" ++#include ++#define HTTP_GET 0 ++#define HTTPD_WS_TYPE_CLOSE 8 ++#define CONFIG_TS_LOG_BUFFER_SIZE 16 ++#define TS_EVENT_BASE_POWER "power" ++#define TS_EVENT_ANY_ID -1 ++typedef struct {const char *uri;int method;esp_err_t (*handler)(httpd_req_t *);void *user_ctx;bool is_websocket,handle_ws_control_frames;} httpd_uri_t; ++static int httpd_register_uri_handler(httpd_handle_t h,const httpd_uri_t *u){(void)h;(void)u;return 0;} ++static int httpd_ws_send_frame(httpd_req_t *r,httpd_ws_frame_t *f){return httpd_ws_send_frame_async(r->handle,r->fd,f);} ++static const char *incoming; ++static int httpd_ws_recv_frame(httpd_req_t *r,httpd_ws_frame_t *f,size_t n){(void)r;if(!incoming)return ESP_FAIL;f->type=1;f->len=strlen(incoming);if(n)memcpy(f->payload,incoming,f->len);return 0;} ++static void *host_heap_malloc(size_t n,unsigned caps){(void)caps;return tracked_malloc(n);} ++static void *host_calloc(size_t n,size_t z){void *p=tracked_malloc(n*z);if(p)memset(p,0,n*z);return p;} ++static void *host_heap_calloc(size_t n,size_t z,unsigned caps){(void)caps;return host_calloc(n,z);} ++static char *host_strdup(const char *s){size_t n=strlen(s)+1;char *p=tracked_malloc(n);if(p)memcpy(p,s,n);return p;} ++static char *host_strndup(const char *s,size_t n){char *p=tracked_malloc(n+1);if(p){memcpy(p,s,n);p[n]=0;}return p;} ++static struct {void (*fn)(void *);void *arg;} shell_task,exec_task; ++static bool task_create_fail,close_during_create,inline_exec; ++static int adapter_create(void(*fn)(void*),const char *name,unsigned stack,void *arg,unsigned priority,TaskHandle_t *out){ ++ (void)stack;(void)priority;(void)out;if(task_create_fail)return 0; ++ if(!strcmp(name,"ssh_poll"))shell_task=(typeof(shell_task)){fn,arg};else exec_task=(typeof(exec_task)){fn,arg}; ++ if(inline_exec && !strcmp(name,"ssh_exec"))fn(arg); ++ return pdPASS; ++} ++static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,void *arg,unsigned p,TaskHandle_t *out,unsigned caps); ++#define malloc tracked_malloc ++#define calloc host_calloc ++#define free tracked_free ++#define strdup host_strdup ++#define strndup host_strndup ++#define heap_caps_malloc host_heap_malloc ++#define heap_caps_calloc host_heap_calloc ++#define xTaskCreate adapter_create ++#define xTaskCreateWithCaps adapter_create_caps ++#include "ts_webui_ws.c" ++#undef malloc ++#undef calloc ++#undef free ++#undef strdup ++#undef strndup ++#undef heap_caps_malloc ++#undef heap_caps_calloc ++#undef xTaskCreate ++#undef xTaskCreateWithCaps ++struct ts_ssh_session_s {bool aborted;}; ++struct ts_ssh_shell_s {bool active;}; ++static unsigned aborts,variable_writes,session_destroys; ++static int remote_failure; ++static void (*remote_hook)(void); ++static bool remote_timeout; ++static struct host_timer {void *id;void (*fn)(TimerHandle_t);bool active;} *host_timer; ++static struct {void (*fn)(void *,uint32_t);void *arg;uint32_t value;TimerHandle_t deleted;} timer_queue[16]; ++static unsigned timer_queued;static bool timer_queue_fail,timer_inline,timer_create_fail,timer_start_fail; ++TimerHandle_t xTimerCreate(const char*n,TickType_t t,BaseType_t repeat,void*id,void(*fn)(TimerHandle_t)){ ++ (void)n;(void)t;(void)repeat;if(timer_create_fail)return NULL;host_timer=calloc(1,sizeof(*host_timer));host_timer->id=id;host_timer->fn=fn;return host_timer; ++} ++void *pvTimerGetTimerID(TimerHandle_t t){return t->id;} ++BaseType_t xTimerStart(TimerHandle_t t,TickType_t wait){(void)wait;if(timer_start_fail)return pdFAIL;t->active=true;return pdPASS;} ++BaseType_t xTimerDelete(TimerHandle_t t,TickType_t wait){(void)wait;if(timer_queue_fail)return pdFAIL;assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){.deleted=t};return pdPASS;} ++BaseType_t xTimerPendFunctionCall(void(*fn)(void*,uint32_t),void *arg,uint32_t v,TickType_t wait){ ++ (void)wait;if(timer_queue_fail)return pdFAIL; ++ if(timer_inline && !timer_queued){fn(arg,v);return pdPASS;} ++ assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){fn,arg,v,NULL};return pdPASS; ++} ++static void timer_pump(void){while(timer_queued){typeof(timer_queue[0]) q=timer_queue[0];memmove(timer_queue,timer_queue+1,--timer_queued*sizeof(*timer_queue));if(q.deleted){free(q.deleted);host_timer=NULL;}else q.fn(q.arg,q.value);}} ++esp_err_t ts_ssh_session_create(const ts_ssh_config_t*c,ts_ssh_session_t *out){(void)c;if(remote_failure==1)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));return *out?ESP_OK:ESP_ERR_NO_MEM;} ++esp_err_t ts_ssh_connect(ts_ssh_session_t s){(void)s;return remote_failure==2?ESP_FAIL:ESP_OK;} ++const char *ts_ssh_get_error(ts_ssh_session_t s){(void)s;return "fake network error";} ++esp_err_t ts_ssh_disconnect(ts_ssh_session_t s){(void)s;return ESP_OK;} ++esp_err_t ts_ssh_session_destroy(ts_ssh_session_t s){session_destroys++;tracked_free(s);return ESP_OK;} ++void ts_ssh_abort(ts_ssh_session_t s){s->aborted=true;aborts++;} ++esp_err_t ts_ssh_shell_open(ts_ssh_session_t s,const ts_shell_config_t*c,ts_ssh_shell_t *out){(void)s;(void)c;if(remote_failure==3)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));(*out)->active=true;return 0;} ++bool ts_ssh_shell_is_active(ts_ssh_shell_t s){return s&&s->active;} ++esp_err_t ts_ssh_shell_close(ts_ssh_shell_t s){tracked_free(s);return 0;} ++esp_err_t ts_ssh_shell_read(ts_ssh_shell_t s,char *b,size_t n,size_t *out){(void)b;(void)n;*out=0;s->active=false;return 0;} ++esp_err_t ts_ssh_shell_write(ts_ssh_shell_t s,const char *b,size_t n,size_t *out){(void)s;(void)b;(void)n;(void)out;return 0;} ++esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t s,uint16_t w,uint16_t h){(void)s;(void)w;(void)h;return 0;} ++esp_err_t ts_ssh_shell_send_signal(ts_ssh_shell_t s,const char *signal){(void)s;(void)signal;return 0;} ++esp_err_t ts_ssh_exec_stream(ts_ssh_session_t s,const char *command,ts_ssh_output_cb_t cb,void *arg,int *code){ ++ (void)command;if(remote_hook)remote_hook();if(remote_timeout && host_timer)host_timer->fn(host_timer); ++ cb("value=42\n",9,false,arg);*code=0;return s->aborted?ESP_ERR_TIMEOUT:ESP_OK; ++} ++esp_err_t ts_keystore_load_private_key(const char *id,char **out,size_t *n){(void)id;(void)out;(void)n;return ESP_FAIL;} ++esp_err_t ts_variable_upsert(const ts_auto_variable_t *v){(void)v;variable_writes++;return 0;} ++esp_err_t ts_console_exec(const char *cmd,ts_cmd_result_t *result){(void)cmd;memset(result,0,sizeof(*result));return 0;} ++esp_err_t ts_console_clear_output_cb(void){return 0;} ++esp_err_t ts_console_set_output_cb(ts_console_output_cb_t cb,void *arg){(void)cb;(void)arg;return 0;} ++void ts_console_request_interrupt(void){} ++esp_err_t ts_log_add_callback(ts_log_callback_t cb,ts_log_level_t l,void *arg,ts_log_callback_handle_t *out){(void)cb;(void)l;(void)arg;*out=(void*)1;return 0;} ++static int remove_log_result; ++esp_err_t ts_log_remove_callback(ts_log_callback_handle_t h){(void)h;return remove_log_result;} ++size_t ts_log_buffer_search(ts_log_entry_t *e,size_t n,ts_log_level_t min,ts_log_level_t max,const char *tag,const char *keyword){(void)e;(void)n;(void)min;(void)max;(void)tag;(void)keyword;return 0;} ++httpd_handle_t ts_http_server_get_handle(void){return (void*)11;} ++void ts_http_server_set_stop_hooks(esp_err_t(*stop)(httpd_handle_t),void(*stopped)(httpd_handle_t)){(void)stop;(void)stopped;} ++static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){(void)caps;if(close_during_create)((ssh_shell_context_t*)arg)->shell->active=false;return adapter_create(fn,n,stack,arg,p,out);} ++static void drive_all(void){for(unsigned i=0;i<12;i++){ts_ws_op_poll();pump();timer_pump();}assert(!timer_queued);} ++static void setup(void){start();memset(s_clients,0,sizeof(s_clients));s_server=(void*)11;s_ws_stopping=false;ts_ws_op_enable();transport_server.closed=peer_closed;for(int fd=1;fd<=2;fd++){reqs[fd]=(httpd_req_t){.handle=(void*)11,.fd=fd};current=(void*)3;assert(add_client(&reqs[fd],WS_CLIENT_TYPE_EVENT)==ESP_OK);}current=(void*)1;} ++static void finish_all(void){drive_all();assert(!ts_ws_op_busy());stop();assert(!live_allocations);} ++static void connect_shell(void){cJSON *j=cJSON_Parse("{\"host\":\"fake\",\"user\":\"fake\"}");current=(void*)3;handle_ssh_connect(&reqs[1],j);current=(void*)1;cJSON_Delete(j);} ++static unsigned terminal_frames,output_frames,connected_frames,disconnecting_frames;static bool output_after_terminal; ++static void observe(httpd_ws_frame_t *f){const char *p=(char*)f->payload;if(strstr(p,"ssh_output")||strstr(p,"ssh_exec_output")){if(terminal_frames)output_after_terminal=true;output_frames++;}if(strstr(p,"ssh_exec_done")||strstr(p,"ssh_exec_error")||strstr(p,"\"status\":\"error\"")||strstr(p,"\"status\":\"closed\""))terminal_frames++;if(strstr(p,"\"status\":\"connected\""))connected_frames++;if(strstr(p,"\"status\":\"disconnecting\""))disconnecting_frames++;} ++static jmp_buf worker_yield; ++static void yield_worker(void){longjmp(worker_yield,1);} ++static void worker_step(void){wait_hook=yield_worker;current=(void*)2;if(!setjmp(worker_yield))worker_fn(NULL);current=(void*)1;wait_hook=NULL;} ++static void sdk_one(void){if(!queued)return;current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(*queue));q.fn(q.arg);current=(void*)1;} ++static void progress(void){sdk_one();if(s_worker){if(s_state==STOPPING)worker_exit();else worker_step();}timer_pump();} ++static void finish_ws(void){drive_all();delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL;for(int i=0;i<32;i++)if(reqs[i].sess_ctx)close_peer(i);ts_webui_ws_stopped((void*)11);assert(!live_allocations);} ++static uint32_t paused_id; ++static void g1_original_callback(void){ ++ close_peer(1); /* HTTPD retires the old target while worker callback is paused */ ++ shell_task.fn(shell_task.arg); /* independent poller exits */ ++ drive_all();open_peer(1);connect_shell(); ++ ts_ws_op_stats_t state;ts_ws_op_stats(TS_WS_OP_SHELL,&state); ++ assert(state.identity==paused_id && state.phase!=OP_FREE && state.refs); ++} ++static void g2_preparing_output(void){ ++ sdk_one();queue_fail=true;worker_step();queue_fail=false;test_now+=100000; ++ drive_all();ts_ws_op_stats_t state;ts_ws_op_stats(TS_WS_OP_EXEC,&state); ++ assert(state.phase==OP_CLOSING && state.preparing==1 && !state.finalizers); ++} ++static void fail_observation_business_continues(void){ ++ ssh_exec_task_params_t *params=exec_task.arg; ++ drive_all();queue_fail=true;ssh_exec_output_callback("before",6,false,params);queue_fail=false;test_now+=100000;drive_all(); ++ assert(!ts_ws_op_is_open(params->op) && ts_webui_ssh_exec_is_running(params->session_id)); ++} ++static void close_snapshot_joiner(void){open_peer(3);ts_ws_op_poll();} ++static void cancel_original_exec(void){ssh_exec_task_params_t *params=exec_task.arg;assert(ts_webui_ssh_exec_cancel(0)==ESP_ERR_INVALID_STATE);assert(ts_webui_ssh_exec_cancel(params->session_id)==ESP_OK);} ++static void validate_exec_frame(httpd_ws_frame_t *f){ ++ const char *p=(char*)f->payload; ++ assert(strstr(p,"\"type\":") && strstr(p,"\"session_id\":")); ++ if(strstr(p,"ssh_exec_output"))assert(strstr(p,"\"data\":")); ++ if(strstr(p,"ssh_exec_error"))assert(strstr(p,"\"error\":")); ++} ++static void stop_progress_shell(void){ ++ if(shell_task.fn && !ts_ws_op_starting(((ssh_shell_context_t*)shell_task.arg)->op)){ ++ void (*fn)(void*)=shell_task.fn;void *arg=shell_task.arg;shell_task.fn=NULL;fn(arg); ++ } ++ progress(); ++} ++static void operation_cross_tests(void){ ++ uint32_t id;ts_ws_op_stats_t ledger; ++ setup();connect_shell();unsigned dc=disconnecting_frames;handle_ssh_disconnect();shell_task.fn(shell_task.arg);finish_all();assert(disconnecting_frames==dc+1); ++ setup();terminal_frames=output_frames=0;output_after_terminal=false;connect_shell(); ++ ssh_shell_context_t *ctx=shell_task.arg;paused_id=ts_ws_op_id(ctx->op); ++ ts_ws_message_t *m=ts_ws_message_text("block",5); ++ assert(ts_ws_transport_submit(ts_ws_op_peer(ctx->op),m,0,0,NULL,NULL)==0);ts_ws_message_release(m); ++ ssh_send_output(ctx,"old",3); /* original producer returns before async rejection */ ++ sdk_one();barrier_name="B06";barrier_action=g1_original_callback;queue_fail=true;worker_step(); ++ queue_fail=false;test_now+=100000;assert(!barrier_action);drive_all();connect_shell();ctx=shell_task.arg; ++ assert(ts_ws_op_id(ctx->op)>paused_id && ts_ws_op_is_open(ctx->op));ssh_cleanup();shell_task.fn(shell_task.arg);finish_all(); ++ puts("PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit)"); ++ ++ setup();terminal_frames=output_frames=0;output_after_terminal=false; ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ ssh_exec_task_params_t *params=exec_task.arg;ts_ws_peer_t peer=*(ts_ws_peer_t*)reqs[1].sess_ctx; ++ m=ts_ws_message_text("block",5);assert(ts_ws_transport_submit(peer,m,0,0,NULL,NULL)==0);ts_ws_message_release(m); ++ ssh_exec_output_callback("A",1,false,params);barrier_name="B02";barrier_action=g2_preparing_output; ++ ssh_exec_output_callback("B",1,false,params);drive_all();assert(!barrier_action && !output_after_terminal && terminal_frames==2); ++ exec_task.fn(exec_task.arg);finish_all(); ++ puts("PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal"); ++ ++ setup();terminal_frames=0;ts_webui_ssh_options_t opts={.timeout_ms=1000,.collect_output=true,.extract_pattern="value=(.*)",.var_name="fake"}; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ timer_queue_fail=true;exec_task.fn(exec_task.arg);drive_all();assert(ts_ws_op_busy()); ++ params=exec_task.arg;assert(params->timer_phase==2 && !params->session); ++ /* A late original timer callback cannot touch freed resources or a new task. */ ++ unsigned before=aborts;host_timer->fn(host_timer);assert(aborts==before); ++ delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);delay_hook=NULL; ++ timer_queue_fail=false;for(unsigned i=0;i<20;i++){test_now+=100000;progress();} ++ assert(!ts_ws_op_busy());finish_ws(); ++ puts("PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement"); ++ ++ setup();assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ timer_queue_fail=true;exec_task.fn(exec_task.arg); ++ for(unsigned i=0;itimer_phase==6);timer_queue_fail=false; ++ delay_hook=progress;esp_err_t stopped=ts_webui_ws_stop((void*)11);delay_hook=NULL; ++ assert(stopped==ESP_OK || stopped==ESP_ERR_TIMEOUT); ++ for(unsigned i=0;i<20;i++){test_now+=100000;progress();}assert(!ts_ws_op_busy());finish_ws(); ++ puts("PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry"); ++ ++ setup();remote_hook=fail_observation_business_continues;unsigned writes=variable_writes; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ exec_task.fn(exec_task.arg);remote_hook=NULL;assert(variable_writes>writes && !aborts);finish_all(); ++ puts("PASS B09 observation failure still executes actual matching and variable updates without aborting remote command"); ++ ++ setup();remote_timeout=true;before=aborts; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ exec_task.fn(exec_task.arg);remote_timeout=false;assert(aborts==before+1);finish_all(); ++ setup();opts.stop_on_match=true;before=aborts; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ exec_task.fn(exec_task.arg);assert(aborts==before+1);finish_all(); ++ puts("PASS original timeout and stop-on-match business abort semantics retained"); ++ ++ setup();before=aborts;remote_hook=cancel_original_exec; ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ exec_task.fn(exec_task.arg);remote_hook=NULL;assert(aborts==before+1);finish_all(); ++ setup();terminal_frames=0; ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ params=exec_task.arg;barrier_name="B07";barrier_action=close_snapshot_joiner; ++ if(ts_ws_op_close_begin(params->op))ts_ws_op_close_finish(params->op,"{\"type\":\"ssh_exec_done\"}"); ++ drive_all();assert(!barrier_action && frames[3]==0 && terminal_frames==2); ++ exec_task.fn(exec_task.arg);finish_all(); ++ puts("PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot"); ++ ++ setup();close_peer(1);close_peer(2); ++ assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ params=exec_task.arg;before=allocations;ssh_exec_output_callback("none",4,false,params);assert(allocations==before); ++ exec_task.fn(exec_task.arg);finish_all(); ++ puts("PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire"); ++ ++ setup();task_create_fail=true;assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==ESP_FAIL);task_create_fail=false;finish_all(); ++ for(unsigned i=0;i<16;i++) { ++ setup();fail_allocation=allocations+i+1; ++ esp_err_t ret=ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id);fail_allocation=0; ++ if(ret==ESP_OK)exec_task.fn(exec_task.arg);finish_all(); ++ } ++ puts("PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed"); ++ for(unsigned i=0;i<48;i++) { ++ setup();assert(ts_webui_ssh_exec_start("fake",22,"u",NULL,"p","cmd",&id)==0); ++ sent_hook=validate_exec_frame;params=exec_task.arg;fail_allocation=allocations+i+1; ++ ssh_exec_output_callback("encoding",8,false,params);fail_allocation=0; ++ exec_task.fn(exec_task.arg);finish_all(); ++ } ++ sent_hook=observe; ++ puts("PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain"); ++ setup();connect_shell();current=(void*)2;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);current=(void*)1; ++ delay_hook=stop_progress_shell;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL;finish_ws(); ++ setup();assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ exec_task.fn(exec_task.arg);ts_ws_op_poll();timer_pump();timer_inline=true;ts_ws_op_poll();timer_inline=false;finish_all(); ++ puts("PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned"); ++ for(unsigned mode=0;mode<2;mode++) { ++ setup();timer_create_fail=mode==0;timer_start_fail=mode==1; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"u",NULL,"p","cmd",&opts,&id)==0); ++ exec_task.fn(exec_task.arg);timer_create_fail=timer_start_fail=false;finish_all(); ++ } ++ puts("PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged"); ++ (void)ledger; ++} ++#ifndef OP_ADAPTER_NO_MAIN ++int main(void){ ++ cJSON_Hooks h={tracked_malloc,tracked_free};cJSON_InitHooks(&h);sent_hook=observe; ++ setup();connect_shell();assert(shell_task.fn && connected_frames==1); ++ ssh_shell_context_t *ctx=shell_task.arg;queue_fail=true;ssh_send_output(ctx,"out",3);queue_fail=false;test_now+=100000;drive_all();assert(terminal_frames==1);shell_task.fn(shell_task.arg);finish_all(); ++ setup();terminal_frames=0;output_after_terminal=false;connect_shell();ctx=shell_task.arg; ++ ssh_send_output(ctx,"out",3);ssh_cleanup();shell_task.fn(shell_task.arg);finish_all();assert(!output_after_terminal); ++ for(int f=0;f<5;f++){setup();terminal_frames=0;unsigned before=connected_frames;task_create_fail=f==0;close_during_create=f==1;remote_failure=f>=2?f-1:0;shell_task.fn=NULL;connect_shell();if(shell_task.fn)shell_task.fn(shell_task.arg);finish_all();assert(connected_frames==before);task_create_fail=close_during_create=false;remote_failure=0;} ++ setup();terminal_frames=0;output_after_terminal=false;uint32_t id; ++ ts_webui_ssh_options_t opts={.collect_output=true,.timeout_ms=1000,.extract_pattern="value=(.*)",.var_name="fake"}; ++ assert(ts_webui_ssh_exec_start_ex("fake",22,"user",NULL,"password","cmd",&opts,&id)==0); ++ exec_task.fn(exec_task.arg);drive_all();assert(terminal_frames==2 && !output_after_terminal && variable_writes);finish_all(); ++ setup();inline_exec=true;assert(ts_webui_ssh_exec_start("fake",22,"user",NULL,"password","cmd",&id)==0);inline_exec=false;finish_all(); ++ operation_cross_tests(); ++ printf("PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=%u\n",session_destroys); ++ return 0; ++} ++ ++#endif diff --git a/docs/repair/ws-operation/design.md b/docs/repair/ws-operation/design.md new file mode 100644 index 0000000..be896d9 --- /dev/null +++ b/docs/repair/ws-operation/design.md @@ -0,0 +1,50 @@ +# Shell/Exec 统一生命周期:实施前设计底稿 + +基线:74b1b646ec4a45f9159bd028e622b13fca5eff75,fix/v0.5.2-reliability-and-prompts。 +本轮开始无已跟踪文件修改;保留 output/、tmp/ 和既有未跟踪 diff-check.txt。 +完整生产源码及原测试保存在 baseline.tar.gz,逐文件 SHA256 在 baseline.json。 + +## 实际依赖和旧写入者 + +HTTPD handler -> handle_ssh_connect -> SSH create/connect/open -> ssh_poll_task -> ssh_send_output。 +HTTPD 输入/resize/signal/disconnect 与 poller 共享 shell/session。 +API / 自动化 -> exec start/start_ex -> exec task -> ts_ssh_exec_stream -> output callback -> 输出、match、变量更新。 +FreeRTOS timer -> timeout callback -> abort;cancel API -> abort。 +两类输出 -> transport submit -> flush -> HTTPD work -> done(可能早于 submit 返回)。 +stop -> pause telemetry -> HTTPD barrier -> producer cleanup -> event unregister_sync/log detach -> manager drain -> TX drain -> worker exit。 + +旧状态写入:connect/poller/cleanup/status/done 共同写 Shell 的 running/state/session/terminal;Exec wrappers/task/output done/terminal flush 共同写 running/params/terminal/result_active;timer 和 cancel 借用全局 session。 +G1:done 减 pending 后仍操作全局 terminal;这时 poller 退出和 terminal settle 可以允许新 connect。 +G2:output callback 已经复制/编码,而 pending 尚未登记;另一交付失败可先封口。 + +## 统一状态表 + +FREE -> STARTING(同锁创建门,创建引用)-> OPEN(资源就绪)-> CLOSING(原子关闭输出门)-> FINALIZING(prepare、output targets、close builder 全部归零,唯一认领)-> TERMINAL_PENDING -> TERMINAL_SETTLED -> RECLAIMING -> FREE。 +STARTING 失败可直接 CLOSING;没有接受业务的创建失败直接丢弃预留并终结观察。 +执行者责任与观察阶段正交:TERMINAL_SETTLED 仍可有 Exec executor;不能复用。 + +## 所有权及线性化点 + +固定 Shell/Exec 各一槽,稳定 portMUX 只保护状态、计数、身份、借用和投递账本。 +创建/stop 共用门;acquire/current-get 在锁内取得原操作引用。新任务参数携带原操作及本代业务资源。 +输出 begin 在 OPEN 检查的同一锁内登记 preparing 和引用;JSON/分配在锁外。 +整批 target 在首个 submit 前登记;票据保留至全部提交返回;每个 token 独立结算,重复回调不得重复减少。 +失败事实与 close 合并在同锁内;回调保活到其最后一次原上下文访问之后。 +首个 close 持 builder 引用冻结接收者;终态 payload/reservation 在 finalizer 中唯一移动;随后回调只结算,不修改已封口 payload。 +终态全部目标登记后逐个提交;finalizer 引用保留至所有 submit 返回。 +executor、borrower、timer、prepare、delivery、finalizer 全部退出后锁内 RECLAIMING;锁外释放业务资源;最后锁内 FREE。 +锁外禁止不持引用访问业务资源;不持 op 锁调用 TX、分配、JSON、SSH、RTOS 或等待。 + +## 迁移映射 + +s_ssh/s_exec_terminal -> slot reservation;pending -> preparing + unsettled;ready/claimed/result_active -> 单一 phase;generation -> 不可变 epoch;global params/session/shell -> 原操作绑定资源。 +status/terminal helpers -> close builder + worker finalizer;done -> token settlement;task/create -> 独立 lease;timer -> 原 params + daemon 排空引用;cancel/input -> 原操作 borrow。 +普通输出各只有一个任务生产者;Shell connecting/connected 在 HTTPD 中准备完毕后才开放 poller,disconnect 不再插入并行普通输出。 +Exec started/output/match 均由同一 executor;观察关闭不跳过收集、匹配、变量和合法取消。 + +## 最小调整与不变范围 + +TX 增加向预留目标绑定固定 peer 的内部入口,保留类别、容量、连接校验和逐目标 exactly-once。 +控制层由现有 subscription worker 推进;不新增任务。终态不承诺浏览器收到。 +Shell input 等借用退出后才允许业务资源销毁;Exec timer 删除之后用同一 timer daemon 的 barrier 归还引用,不能把 xTimerStop 返回当作回调退出。 +不改变 SSH 匹配规则、变量语义、硬件、全局事件和遥测策略。 diff --git a/docs/repair/ws-operation/diff-check.txt b/docs/repair/ws-operation/diff-check.txt new file mode 100644 index 0000000..c79fde8 --- /dev/null +++ b/docs/repair/ws-operation/diff-check.txt @@ -0,0 +1 @@ +PASS: git diff --check diff --git a/docs/repair/ws-operation/f1-f2-tests.txt b/docs/repair/ws-operation/f1-f2-tests.txt new file mode 100644 index 0000000..854d7e5 --- /dev/null +++ b/docs/repair/ws-operation/f1-f2-tests.txt @@ -0,0 +1,23 @@ +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F2: protection transition survives ordinary log saturation +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS original peer and operation identity isolation across reconnect +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-operation/historical-f1-f2.txt b/docs/repair/ws-operation/historical-f1-f2.txt new file mode 100644 index 0000000..1b6c5eb --- /dev/null +++ b/docs/repair/ws-operation/historical-f1-f2.txt @@ -0,0 +1,4 @@ +Frozen production snapshot hashes verified +F1 assertion: accepted SSH output enqueue failure reaches session and error frame: FAIL (stream still normal / no error frame) +F2 assertion: protection transition survives ordinary log pool saturation: FAIL (no protection frame) +CONFIRMED: both failures are behavioral assertions, not compilation or cleanup failures diff --git a/docs/repair/ws-operation/host-tests.txt b/docs/repair/ws-operation/host-tests.txt new file mode 100644 index 0000000..88ff604 --- /dev/null +++ b/docs/repair/ws-operation/host-tests.txt @@ -0,0 +1,23 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-operation/operation-tests.txt b/docs/repair/ws-operation/operation-tests.txt new file mode 100644 index 0000000..b6d8772 --- /dev/null +++ b/docs/repair/ws-operation/operation-tests.txt @@ -0,0 +1,2 @@ +PASS 16 failure schedules: encode/SDK/socket/stale peer, early/deferred done, duplicate tokens do not double-settle +PASS production operation/TX: 36 barrier schedules, ticket/target ledgers and B09 executor retention; destroyed=36 diff --git a/docs/repair/ws-operation/public-headers.json b/docs/repair/ws-operation/public-headers.json new file mode 100644 index 0000000..3cee9d3 --- /dev/null +++ b/docs/repair/ws-operation/public-headers.json @@ -0,0 +1,46 @@ +{ + "components/ts_security/include/ts_ssh_service.h": "73fbddabe3eaed6a191b90b1644eb50eb440509723c92f4a61788c2306596102", + "components/ts_security/include/ts_known_hosts.h": "4b1244556d046e0057ba0d372498f92d263e43183975d5e55d0bbaea669b0934", + "components/ts_security/include/ts_ssh_log_watch.h": "08677f37f9ee0a3620f6ed38770c4f1977d3b70787e96e57db0f934de5c5452f", + "components/ts_security/include/ts_crypto.h": "371ac3b950f7185eaa21a710c4e823ed806ab337d573cfffdcfe58656aeee8c0", + "components/ts_security/include/ts_ssh_shell.h": "19a5f9706d3db36baa967f5ecefb77735e3771ac176e2e680a89be342f39c8e1", + "components/ts_security/include/ts_scp.h": "5801a44ef598560d9eef3265ec5b891b494e2682b3049834d3694abe0f86f175", + "components/ts_security/include/ts_ssh_commands_config.h": "d1fa1bbc2762bc4accf697db09959396cb5d82bb67ba1806a0cd4f9b45305352", + "components/ts_security/include/ts_ssh_probe.h": "697c24c0ff5244397d3483997357a81311cbd24b718d64b845efd96e19979e43", + "components/ts_security/include/ts_keystore.h": "55831771c42ae32640dc6ce1d7755f3487149f71f42d1f1ca7451af2ff675f40", + "components/ts_security/include/ts_sftp.h": "6d0c9ab1ac7dd3eab5d820798f543be18e2de1d43028dc72ca088b3ec13ab1fe", + "components/ts_security/include/ts_security.h": "01cf0f2c1ee2599c0d733ac5d7466e73358fe5483aad23d654c2e6b99c039f35", + "components/ts_security/include/ts_ssh_client.h": "ceb00ed29965279a154e061638b58769e148ea370f5435de48c90c1c8d90f928", + "components/ts_security/include/ts_ssh_hosts_config.h": "48d27c0cdeb6b0f462d41eaef281b6f2afe6e460b810a61f2f98278d0609280d", + "components/ts_security/include/ts_port_forward.h": "a249f758369a81a7db44f71e4aed0511cd4f5aa932cc4bde33b29c393b5d39be", + "components/ts_automation/include/ts_automation_types.h": "e2c9becd036d1322fdf5f40ae67df8a6d23c53f411497368e61fbe557a9d597c", + "components/ts_automation/include/ts_source_manager.h": "42f2e1281ea0644a47013d3eb1a35cf6ecfc6115627b75c8fda3dfb7b4e0f78d", + "components/ts_automation/include/ts_rule_engine.h": "70d0d72afb2ebeffc278e1c844663049a5624cd2365311c0116f40f057b76a74", + "components/ts_automation/include/ts_action_manager.h": "af18f369c569389caf2ca033f34b234a18b724577334cc5731f9d0d449f85485", + "components/ts_automation/include/ts_variable.h": "136b371f4d0fab848c8c2ae15de4993b8786479af64e4c87974c8e26d1be009b", + "components/ts_automation/include/ts_rule_codec.h": "501ed7dbec67e52807997cc905b41bea86d71f119cd4b31b9f460c0e0ba54a26", + "components/ts_automation/include/ts_automation.h": "fec1551e90c8b0e0acb0b4355c695d90213d94247659db99670c9782c69bdc08", + "components/ts_drivers/include/ts_device_ctrl.h": "0d203054b4b8dfe970d408c706fa1e123973b9bdc52583eec63162eee25a8879", + "components/ts_drivers/include/ts_usb_mux.h": "4dde492aa085eab2024a12477036b80583b9e00a6ee3200164ec6b2b5a3b5080", + "components/ts_drivers/include/ts_power.h": "1961071837745a2e5db6290e65bd4cdf8465a6e42b181b24f13ec642a80cc45d", + "components/ts_drivers/include/ts_fan.h": "2a30df271570bff942383c46e368f232db484627bbbbb29b77a49a2155304cba", + "components/ts_drivers/include/ts_drivers.h": "56d740b76b1401407f81099e521cd514e617fb1cdd3aaf9eab727a86dd327fd2", + "components/ts_drivers/include/ts_power_monitor.h": "1e1b1f246f6cea8d05881e9960d2db7fd25c4185544ff8659dd8556d8f68636e", + "components/ts_drivers/include/ts_compute_monitor.h": "b85ce79f490986e6b64ec3b12bef425576b5dec0121c0237f8cab34aab772703", + "components/ts_drivers/include/ts_temp_source.h": "195c577b4f4e51efe4ad19315679dac3944f53eb72bbc94392717b3426067000", + "components/ts_drivers/include/ts_power_policy.h": "1f8475392cbaab61e90470ee0a246a67f4f8760392026318e2a56ea1058cfbc3", + "components/ts_console/include/ts_console_args.h": "98084002ced0297f0f92824510271e56af90199442518c392d1fba3907cf624b", + "components/ts_console/include/ts_cmd_all.h": "2f76f6ec1ba074d28deb15efb4d0272607604d0b809a52fdf506b15d5659cb52", + "components/ts_console/include/ts_script.h": "a7f8c453393ac94e2c4d562b1bd8a715a21884ab7fbf1f2e19ea5acbf1ea2abf", + "components/ts_console/include/ts_console.h": "f107554abcf4de2655e2bb129f5bece338ca9126e89a546b102a9bff9d92400a", + "components/ts_console/include/ts_i18n.h": "9ce79a7c63c72fc49899b7614bf9a751808183de90b5ba2a228e2fffea1f1d9e", + "components/ts_net/include/ts_net_manager.h": "6ad22613972f51af05eb6d468c04763808d92c1d6a6b0a7225911b24f9c0d9a5", + "components/ts_net/include/ts_nat.h": "1721b9c499ca0da09eb402d7db9211604a7a3414b6e2e7cf88169f872365a229", + "components/ts_net/include/ts_net.h": "2ddcd9233f0f5f63a83fdc6f3d09de3118b5b1cced5d9b009b3126c3b872a98b", + "components/ts_net/include/ts_eth.h": "9f8952c77ade85741afb38aa48f3fb689a94164a2c598eb6c7df9344948cf8ce", + "components/ts_net/include/ts_https_server.h": "f4c25017722b69f2f1bae48df34aa595f15d186ad3ec652b7be9d034e184bc79", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/include/ts_dhcp_server.h": "64e5e854f9b8fd7182f92dfafe594f3d8f1288ddecbbbec2c89b3aabee950c51", + "components/ts_net/include/ts_wifi.h": "25614f917387174bbbb7618010885353008e4488262303b314b87b78ae9f0905", + "components/ts_net/include/ts_time_sync.h": "e3ebf9da5b0c7b30a50a67fe07547e2c7fefd588474552579f4a2bc15ace8ca4" +} diff --git a/docs/repair/ws-operation/publication-adapter.txt b/docs/repair/ws-operation/publication-adapter.txt new file mode 100644 index 0000000..7febc5e --- /dev/null +++ b/docs/repair/ws-operation/publication-adapter.txt @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=84 diff --git a/docs/repair/ws-operation/publication-f1f2.txt b/docs/repair/ws-operation/publication-f1f2.txt new file mode 100644 index 0000000..854d7e5 --- /dev/null +++ b/docs/repair/ws-operation/publication-f1f2.txt @@ -0,0 +1,23 @@ +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F2: protection transition survives ordinary log saturation +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS original peer and operation identity isolation across reconnect +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-operation/publication-gate.md b/docs/repair/ws-operation/publication-gate.md new file mode 100644 index 0000000..2a37098 --- /dev/null +++ b/docs/repair/ws-operation/publication-gate.md @@ -0,0 +1,20 @@ +# PR #42 更新前检查(2026-09-26) + +结论:**可以推送**。用户本轮已授权追加提交并更新现有 PR;不合并、不发布、不操作设备。 + +发布前本地 HEAD、Fork 分支和上游 PR head 均为 `74b1b646ec4a45f9159bd028e622b13fca5eff75`。范围为 `changes.json` 列出的 22 个生产/测试文件及本目录实现、基线和验证材料。`output/`、`tmp/` 和另一份未跟踪的 runtime reviewer diff-check 不包含在提交中。 + +检查了创建租约、ticket/close 同锁、输出与终态结算、旧回调保活、原 timer 排空、停止失败后依赖保留,以及 SDK 最终发送边界的现有断言。没有发现阻止本次发布供审查的问题;这不是穷尽并发证明。 + +本次重新执行(IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf,DEVELOPER_DIR=/Library/Developer/CommandLineTools): + +- `bash tests/ws_subscriptions/run_operation.sh`:通过,publication-operation.txt。 +- `bash tests/ws_subscriptions/run_operation_adapter.sh`:通过,publication-adapter.txt。 +- `bash tests/ws_subscriptions/run_reviewer.sh`:通过,publication-reviewer.txt。 +- `bash tests/ws_subscriptions/run_f1_f2.sh`:通过,publication-f1f2.txt。 +- `python3 tests/release/test_release.py`:通过,publication-release.txt。 +- `git diff --check`:生产/测试修改通过。 + +逐文件核对 changes.json,所有生产/测试 SHA256 及 changes.patch 哈希一致;build-artifacts.json 的 app、www 和独立 sdkconfig 实物哈希一致。本次发布前未重复完整编译、运行时、证书和浏览器套件,沿用同一源码快照在实施阶段实际执行的日志;不引用旧 PR head 的 CI 为新提交背书。新增回归仍未接入 CI。 + +README 的未执行/设备验收清单保持有效。资源测量是目标工具链静态帧与 sizeof,不是板上调用链峰值;传输结算不是浏览器收到确认。changes.json 的 local-only scope 和 working-tree-status.txt 保留为实现阶段历史快照,不代表本轮发布授权。 diff --git a/docs/repair/ws-operation/publication-operation.txt b/docs/repair/ws-operation/publication-operation.txt new file mode 100644 index 0000000..b6d8772 --- /dev/null +++ b/docs/repair/ws-operation/publication-operation.txt @@ -0,0 +1,2 @@ +PASS 16 failure schedules: encode/SDK/socket/stale peer, early/deferred done, duplicate tokens do not double-settle +PASS production operation/TX: 36 barrier schedules, ticket/target ledgers and B09 executor retention; destroyed=36 diff --git a/docs/repair/ws-operation/publication-release.txt b/docs/repair/ws-operation/publication-release.txt new file mode 100644 index 0000000..e76e6ef --- /dev/null +++ b/docs/repair/ws-operation/publication-release.txt @@ -0,0 +1,5 @@ +... +---------------------------------------------------------------------- +Ran 3 tests in 0.003s + +OK diff --git a/docs/repair/ws-operation/publication-reviewer.txt b/docs/repair/ws-operation/publication-reviewer.txt new file mode 100644 index 0000000..5a5cfbd --- /dev/null +++ b/docs/repair/ws-operation/publication-reviewer.txt @@ -0,0 +1,15 @@ +PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds +PASS HTTPD barrier timeout retains worker and retry state +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-operation/resources.txt b/docs/repair/ws-operation/resources.txt new file mode 100644 index 0000000..f5da5e2 --- /dev/null +++ b/docs/repair/ws-operation/resources.txt @@ -0,0 +1,369 @@ +ts_ws_operation.c +00000000 00000001 b s_op_accepting +00000000 00000001 b s_op_tick +00000000 00000007 T ts_ws_op_id +00000000 00000008 b s_op_delivery +00000000 00000008 d s_op_lock +00000000 00000008 b s_op_sequence +00000000 0000000e r __func__$0 +00000000 0000000e r __func__$1 +00000000 0000000e r __func__$9 +00000000 00000010 r __func__$8 +00000000 00000010 R op_sizes +00000000 00000011 r __func__$4 +00000000 00000011 r __func__$7 +00000000 00000012 T ts_ws_op_peer +00000000 00000015 t fail_locked +00000000 00000016 r __func__$3 +00000000 00000017 r __func__$2 +00000000 00000017 r __func__$5 +00000000 00000017 r __func__$6 +00000000 0000001c T ts_ws_op_data +00000000 0000001c T ts_ws_op_set_maintenance +00000000 0000001f T ts_ws_op_needs_tick +00000000 00000022 T ts_ws_op_enable +00000000 00000022 T ts_ws_op_executing +00000000 00000022 T ts_ws_op_stop_admission +00000000 00000023 T ts_ws_op_starting +00000000 00000024 t close_locked +00000000 00000024 T ts_ws_op_is_open +00000000 0000002c T ts_ws_op_open +00000000 00000030 T ts_ws_op_close_begin +00000000 00000032 t close_snapshot +00000000 00000033 T ts_ws_op_stats +00000000 00000034 T ts_ws_op_retain +00000000 0000003a T ts_ws_op_bind +00000000 0000003c T ts_ws_op_executor_take +00000000 0000003c T ts_ws_op_release +00000000 0000003e T ts_ws_op_busy +00000000 00000044 T ts_ws_op_executor_done +00000000 0000004a t fallback +00000000 00000070 T ts_ws_op_discard +00000000 00000076 T ts_ws_op_acquire +00000000 00000086 T ts_ws_op_close_finish +00000000 00000088 T ts_ws_op_output_begin +00000000 0000014c T ts_ws_op_create +00000000 00000182 t settle_target +00000000 000001fe T ts_ws_op_output_finish +00000000 0000049e T ts_ws_op_poll +00000000 00000740 b s_ops + + +/tmp/tianshan-op-build/resources/ts_ws_operation.c.o: file format elf32-xtensa-le + +Contents of section .rodata.op_sizes: + 0000 a0030000 18010000 10000000 58000000 ............X... + +/tmp/tianshan-op-build/resources/ts_ws_operation.c:88:13:close_locked 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:111:13:fail_locked 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:92:13:close_snapshot 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:29:6:ts_ws_op_enable 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:30:6:ts_ws_op_stop_admission 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:31:6:ts_ws_op_busy 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:52:6:ts_ws_op_bind 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:55:6:ts_ws_op_set_maintenance 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:56:6:ts_ws_op_needs_tick 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:57:7:ts_ws_op_data 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:58:10:ts_ws_op_id 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:100:13:fallback 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:59:14:ts_ws_op_peer 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:60:20:ts_ws_op_acquire 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:66:6:ts_ws_op_retain 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:67:6:ts_ws_op_release 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:70:6:ts_ws_op_executor_take 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:73:6:ts_ws_op_executor_done 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:76:6:ts_ws_op_executing 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:77:6:ts_ws_op_open 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:80:6:ts_ws_op_is_open 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:81:6:ts_ws_op_starting 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:82:6:ts_ws_op_discard 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:36:20:ts_ws_op_create 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:96:6:ts_ws_op_close_begin 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:106:6:ts_ws_op_close_finish 288 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:114:13:settle_target 48 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:136:6:ts_ws_op_output_begin 32 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:145:6:ts_ws_op_output_finish 176 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:171:6:ts_ws_op_poll 576 static +/tmp/tianshan-op-build/resources/ts_ws_operation.c:217:6:ts_ws_op_stats 32 static + +ts_webui_ws.c +00000000 00000001 b s_log_streaming_enabled +00000000 00000001 b s_ws_stopping +00000000 00000004 b s_log_callback_handle +00000000 00000004 b s_output_mutex +00000000 00000004 b s_power_event_handle +00000000 00000004 b s_server +00000000 00000004 d s_terminal_client_fd +00000000 00000004 b s_terminal_mutex +00000000 00000004 b s_terminal_output_buf +00000000 00000004 b s_terminal_output_len +00000000 0000000c R adapter_sizes +00000000 0000000d r __func__$0 +00000000 0000000e r __func__$1 +00000000 00000018 r s_level_names +00000000 0000001a t exec_timer_drained +00000000 00000022 T ts_webui_ssh_exec_start +00000000 00000027 t ssh_cleanup +00000000 00000028 t exec_abort +00000000 0000002b T ts_webui_ssh_result_free +00000000 0000002c t ssh_disconnecting +00000000 0000002c T ts_webui_ssh_exec_is_running +00000000 0000002f T ts_webui_ws_stopped +00000000 00000032 t handle_ssh_disconnect +00000000 00000032 t shell_destroy +00000000 00000034 T ts_webui_broadcast +00000000 00000042 t has_log_clients +00000000 00000042 t shell_resources_close +00000000 00000045 t power_state_to_string +00000000 0000004c t update_log_stream_state +00000000 00000052 t ssh_exec_timeout_callback +00000000 00000059 T ts_webui_ssh_exec_cancel +00000000 0000005f t exec_retry_timer_drain +00000000 00000062 t handle_ssh_signal +00000000 00000068 t handle_ssh_resize +00000000 0000006c T ts_webui_log_stream_enable +00000000 0000006e t handle_ssh_input +00000000 00000078 t ssh_close +00000000 0000007d t peer_closed +00000000 0000007e T ts_webui_ssh_exec_start_ex +00000000 00000089 T ts_webui_broadcast_event +00000000 0000009c t terminal_output_cb +00000000 000000a0 b s_clients +00000000 000000aa t exec_destroy +00000000 000000ac t ssh_request_error +00000000 000000b5 t ssh_start_status +00000000 000000bf t add_client +00000000 000000ca t ssh_poll_task +00000000 000000cc t ssh_send_output +00000000 000000e4 t set_client_role +00000000 000000f6 t cleanup_disconnected_client +00000000 00000122 t exec_maintenance +00000000 0000013e T ts_webui_ws_stop +00000000 00000158 t log_ws_callback +00000000 00000163 t power_policy_event_handler +00000000 0000017a t simple_pattern_match +00000000 00000214 t handle_terminal_command +00000000 00000230 t start_terminal_session +00000000 00000246 T ts_webui_ws_init +00000000 000002b6 t handle_ssh_connect +00000000 00000505 t ts_webui_ssh_exec_start_ex_impl +00000000 0000065e t ssh_exec_output_callback +00000000 00000aae t ws_handler +00000000 00000b92 t ssh_exec_task + + +/tmp/tianshan-op-build/resources/ts_webui_ws.c.o: file format elf32-xtensa-le + +Contents of section .rodata.adapter_sizes: + 0000 14000000 18030000 88000000 ............ + +/tmp/tianshan-op-build/resources/ts_webui_ws.c:123:20:power_state_to_string 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1197:13:has_log_clients 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:136:13:power_policy_event_handler 736 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:179:13:ssh_request_error 48 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:381:18:add_client 96 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:357:13:terminal_output_cb 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:399:13:handle_terminal_command 64 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:216:13:ssh_send_output 320 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:199:13:shell_destroy 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1601:13:exec_destroy 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:233:18:ssh_start_status 80 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:207:13:ssh_close 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:247:13:ssh_disconnecting 320 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:192:13:shell_resources_close 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:254:13:ssh_poll_task 2096 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:323:13:handle_ssh_input 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:330:13:handle_ssh_disconnect 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:274:13:ssh_cleanup 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1562:13:exec_timer_drained 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:337:13:handle_ssh_signal 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:344:13:handle_ssh_resize 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1592:13:exec_retry_timer_drain 48 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1077:6:ts_webui_ws_stopped 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1132:13:log_ws_callback 48 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1336:13:exec_abort 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1552:13:ssh_exec_timeout_callback 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1260:13:simple_pattern_match 48 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1613:13:ssh_exec_task 560 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1343:13:ssh_exec_output_callback 1088 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1568:13:exec_maintenance 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1977:18:ts_webui_ssh_exec_start_ex_impl 528 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:948:11:ts_webui_ws_init 64 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1084:11:ts_webui_broadcast 48 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1097:11:ts_webui_broadcast_event 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1174:11:ts_webui_log_stream_enable 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1210:13:update_log_stream_state 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:571:13:cleanup_disconnected_client 96 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:608:13:peer_closed 128 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:109:13:set_client_role 128 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:482:13:start_terminal_session 96 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:281:13:handle_ssh_connect 208 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:616:18:ws_handler 176 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:1041:11:ts_webui_ws_stop 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:2169:11:ts_webui_ssh_exec_start_ex 144 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:2184:11:ts_webui_ssh_exec_start 48 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:2191:6:ts_webui_ssh_result_free 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:2200:11:ts_webui_ssh_exec_cancel 32 static +/tmp/tianshan-op-build/resources/ts_webui_ws.c:2212:6:ts_webui_ssh_exec_is_running 32 static + +ts_ws_subscriptions.c +00000000 00000001 b s_stop_owner +00000000 00000004 b s_entries +00000000 00000004 b s_outstanding +00000000 00000004 b s_state +00000000 00000004 b s_subscription_cursor +00000000 00000004 b s_topic_cursor +00000000 00000004 b s_worker +00000000 00000008 b s_allocation_retry_at +00000000 00000008 d s_lock +00000000 00000008 b s_sequence +00000000 0000000c b s_handlers +00000000 0000001a t wake_locked +00000000 0000001c r fields +00000000 0000001c r metrics +00000000 0000001f T ts_ws_subscriptions_wake +00000000 00000028 t leave +00000000 00000035 t after_ms +00000000 00000037 t enter +00000000 00000038 t topic_id +00000000 0000003a T ts_ws_subscriptions_in_context +00000000 0000003d t metric_needed +00000000 00000042 t wait_ticks +00000000 00000047 t find_revision +00000000 0000004e t delivery_valid +00000000 0000006a t ts_ws_json_reference +00000000 00000079 t reserve +00000000 0000007a T ts_ws_subscriptions_pause +00000000 0000007b T ts_ws_client_disconnected +00000000 00000084 r topics +00000000 00000096 t telemetry_worker +00000000 000000a6 t submit +00000000 000000c1 T ts_ws_unsubscribe +00000000 000000c8 t delivery_done +00000000 000000ce t event_handler +00000000 000000e6 T ts_ws_subscriptions_drain +00000000 000000f0 T ts_ws_subscriptions_init +00000000 00000128 b s_stats +00000000 000001b4 T ts_ws_broadcast_to_topic +00000000 000001d3 T ts_ws_subscriptions_deinit +00000000 00000209 t next_wait +00000000 000002e5 T ts_ws_subscribe +00000000 00000305 t collect_batch +00000000 00000460 b s_events +00000000 00000548 t run_batch +00000000 00000a00 b s_subs + +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:70:16:after_ms 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:97:24:find_revision 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:273:19:wait_ticks 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:103:13:delivery_valid 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:144:13:metric_needed 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:85:13:enter 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:75:13:wake_locked 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:128:13:reserve 80 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:93:13:leave 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:111:13:delivery_done 48 static +/Users/massif/TianshanOS/components/ts_webui/include/ts_ws_transport.h:65:20:ts_ws_json_reference 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:150:13:collect_batch 176 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:136:13:submit 96 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:198:13:run_batch 3360 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:281:19:next_wait 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:301:13:telemetry_worker 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:80:12:topic_id 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:76:6:ts_ws_subscriptions_wake 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:353:11:ts_ws_subscriptions_pause 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:366:11:ts_ws_subscriptions_drain 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:386:11:ts_ws_subscriptions_deinit 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:332:11:ts_ws_subscriptions_init 96 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:419:11:ts_ws_subscribe 144 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:453:11:ts_ws_unsubscribe 96 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:464:6:ts_ws_client_disconnected 96 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:470:6:ts_ws_broadcast_to_topic 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:317:13:event_handler 32 static +/tmp/tianshan-op-build/resources/ts_ws_subscriptions.c:495:6:ts_ws_subscriptions_in_context 32 static + +Removed baseline Shell/Exec globals (target): +00000000 00000001 b s_exec_cancel_requested +00000000 00000001 b s_exec_output_failed +00000000 00000001 b s_exec_result_active +00000000 00000001 b s_exec_running +00000000 00000001 b s_exec_terminal_claimed +00000000 00000001 b s_exec_terminal_ready +00000000 00000001 b s_ssh_output_failed +00000000 00000001 b s_ssh_poll_alive +00000000 00000001 b s_ssh_running +00000000 00000001 b s_ssh_terminal_ready +00000000 00000004 b s_exec_creators +00000000 00000004 b s_exec_output_pending +00000000 00000004 b s_exec_params +00000000 00000004 b s_exec_result_count +00000000 00000004 b s_exec_session +00000000 00000004 b s_exec_session_id +00000000 00000004 b s_exec_task +00000000 00000004 b s_exec_timeout_timer +00000000 00000004 d s_ssh_client_fd +00000000 00000004 b s_ssh_generation +00000000 00000004 b s_ssh_output_pending +00000000 00000004 b s_ssh_result_pending +00000000 00000004 b s_ssh_session +00000000 00000004 b s_ssh_shell +00000000 00000004 b s_ssh_state +00000000 00000020 b s_ssh_peer +00000000 00000088 b s_exec_terminal +00000000 00000088 b s_ssh_terminal +00000000 00000100 b s_exec_result_peers +Total removed static bytes: 630 + +/tmp/tianshan-op-build/resources/baseline_ws.o: file format elf32-xtensa-le + +Contents of section .rodata.old_sizes: + 0000 e8020000 5c000000 2c000000 ....\...,... +/tmp/tianshan-op-build/resources/baseline_ws.c:142:20:power_state_to_string 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:208:13:ssh_status_valid 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:204:13:ssh_generation_valid 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1425:13:has_log_clients 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:155:13:power_policy_event_handler 736 static +/tmp/tianshan-op-build/resources/baseline_ws.c:214:13:ssh_request_error 48 static +/tmp/tianshan-op-build/resources/baseline_ws.c:617:18:add_client 96 static +/tmp/tianshan-op-build/resources/baseline_ws.c:197:13:ssh_terminal_done 48 static +/tmp/tianshan-op-build/resources/baseline_ws.c:236:13:ssh_terminal_flush 192 static +/tmp/tianshan-op-build/resources/baseline_ws.c:287:18:ssh_send_status 128 static +/tmp/tianshan-op-build/resources/baseline_ws.c:593:13:terminal_output_cb 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:635:13:handle_terminal_command 64 static +/tmp/tianshan-op-build/resources/baseline_ws.c:227:13:ssh_output_done 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:252:13:ssh_send_output 96 static +/tmp/tianshan-op-build/resources/baseline_ws.c:330:13:ssh_poll_task 2096 static +/tmp/tianshan-op-build/resources/baseline_ws.c:553:13:handle_ssh_input 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:573:13:handle_ssh_signal 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:581:13:handle_ssh_resize 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1305:6:ts_webui_ws_stopped 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1360:13:log_ws_callback 48 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1779:13:ssh_exec_timeout_callback 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1790:13:ssh_exec_terminal_flush 272 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1806:13:ssh_exec_terminal_publish 240 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1558:13:ssh_exec_output_done 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1567:13:ssh_exec_stream_publish 352 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1482:13:simple_pattern_match 48 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1821:13:ssh_exec_task 560 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1584:13:ssh_exec_output_callback 528 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2190:18:ts_webui_ssh_exec_start_impl 64 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2307:18:ts_webui_ssh_exec_start_ex_impl 528 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1186:11:ts_webui_ws_init 64 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1312:11:ts_webui_broadcast 48 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1325:11:ts_webui_broadcast_event 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1402:11:ts_webui_log_stream_enable 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1438:13:update_log_stream_state 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:128:13:set_client_role 128 static +/tmp/tianshan-op-build/resources/baseline_ws.c:386:13:ssh_cleanup 80 static +/tmp/tianshan-op-build/resources/baseline_ws.c:564:13:handle_ssh_disconnect 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:424:13:handle_ssh_connect 336 static +/tmp/tianshan-op-build/resources/baseline_ws.c:807:13:cleanup_disconnected_client 96 static +/tmp/tianshan-op-build/resources/baseline_ws.c:848:13:peer_closed 64 static +/tmp/tianshan-op-build/resources/baseline_ws.c:718:13:start_terminal_session 96 static +/tmp/tianshan-op-build/resources/baseline_ws.c:854:18:ws_handler 176 static +/tmp/tianshan-op-build/resources/baseline_ws.c:1278:11:ts_webui_ws_stop 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2287:11:ts_webui_ssh_exec_start 64 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2510:11:ts_webui_ssh_exec_start_ex 64 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2531:6:ts_webui_ssh_result_free 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2540:11:ts_webui_ssh_exec_cancel 32 static +/tmp/tianshan-op-build/resources/baseline_ws.c:2554:6:ts_webui_ssh_exec_is_running 32 static diff --git a/docs/repair/ws-operation/reviewer-tests.txt b/docs/repair/ws-operation/reviewer-tests.txt new file mode 100644 index 0000000..5a5cfbd --- /dev/null +++ b/docs/repair/ws-operation/reviewer-tests.txt @@ -0,0 +1,15 @@ +PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds +PASS HTTPD barrier timeout retains worker and retry state +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-operation/runtime-tests.txt b/docs/repair/ws-operation/runtime-tests.txt new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ws-operation/runtime-tests.txt @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ws-operation/webui-browser-tests.txt b/docs/repair/ws-operation/webui-browser-tests.txt new file mode 100644 index 0000000..9cfd521 --- /dev/null +++ b/docs/repair/ws-operation/webui-browser-tests.txt @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (1092.409208ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (274.892ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (337.649542ms) +✔ en-US: initial language failure blocks controls and retry recovers (326.844958ms) +✔ delayed language package and rapid switches keep the latest requested language (280.721708ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (368.758708ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (274.711625ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (354.324708ms) +✔ initial delayed language keeps controls inert until the real package arrives (256.482916ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (363.415333ms) +✔ terminal can initialize after failed resource load using newly served resources (393.30675ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (1029.861041ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (235.074333ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (176.087709ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (237.022833ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (259.473583ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (253.557584ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (188.002709ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (199.426708ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (174.676542ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (205.306916ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (211.127292ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (172.939ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (259.282667ms) +✔ R3: late validation cannot revive an old apply entry en-US (250.014916ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (266.961583ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (233.536125ms) +✔ R6: fixed upload destination and separate refresh failure en-US (244.558666ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (235.698667ms) +✔ R2: authenticated startup initializes once (273.004792ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (215.82775ms) +✔ R4/R5: newest result wins over late success and late failure (249.914042ms) +✔ R3: overlapping writes to one path cannot claim current verified content (243.040417ms) +✔ R2: disposed page only removes its dashboard callback (275.836791ms) +✔ R2: stale finally cannot unlock the new page read (235.1505ms) +✔ R1: delayed sign-out does not clear a newer sign-in (233.821958ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (331.39075ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (351.655042ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 7602.177834 diff --git a/docs/repair/ws-operation/webui-node-tests.txt b/docs/repair/ws-operation/webui-node-tests.txt new file mode 100644 index 0000000..c2e85a7 --- /dev/null +++ b/docs/repair/ws-operation/webui-node-tests.txt @@ -0,0 +1,51 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (16.332375ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.440833ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (7.731916ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.914334ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.687666ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.38425ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (5.67325ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.972833ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.889375ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.1595ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.126ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (4.759334ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.89ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.649041ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.921583ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.677458ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.605542ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.707541ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.931792ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.72525ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.762583ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (8.599458ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.5585ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (4.531958ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.986333ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.34275ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (5.486833ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (6.551667ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (5.069083ms) +✔ en-US: upload and download aggregates cover all success and all failure (4.762625ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (5.380167ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.737167ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.581917ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.998458ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.881417ms) +✔ en-US: unknown stop result never escalates to forced termination (4.388208ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (6.262375ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.118292ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 258.231833 diff --git a/docs/repair/ws-operation/working-tree-status.txt b/docs/repair/ws-operation/working-tree-status.txt new file mode 100644 index 0000000..3ea14cb --- /dev/null +++ b/docs/repair/ws-operation/working-tree-status.txt @@ -0,0 +1,26 @@ + M components/ts_webui/CMakeLists.txt + M components/ts_webui/include/ts_ws_subscriptions.h + M components/ts_webui/include/ts_ws_transport.h + M components/ts_webui/src/ts_webui_ws.c + M components/ts_webui/src/ts_ws_subscriptions.c + M components/ts_webui/src/ts_ws_transport.c + M tests/ws_subscriptions/run_f1_f2.sh + M tests/ws_subscriptions/run_reviewer.sh + M tests/ws_subscriptions/test_f1_f2.c + M tests/ws_subscriptions/test_init.c + M tests/ws_subscriptions/test_manager.c + M tests/ws_subscriptions/test_reviewer.c +?? components/ts_webui/include/ts_ws_operation.h +?? components/ts_webui/src/ts_ws_operation.c +?? docs/repair/ws-operation/ +?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt +?? output/ +?? tests/ws_subscriptions/baseline_operation_adapter.c +?? tests/ws_subscriptions/replay_operation_baseline.py +?? tests/ws_subscriptions/run_operation.sh +?? tests/ws_subscriptions/run_operation_adapter.sh +?? tests/ws_subscriptions/stubs/esp_console.h +?? tests/ws_subscriptions/stubs/freertos/timers.h +?? tests/ws_subscriptions/test_operation.c +?? tests/ws_subscriptions/test_operation_adapter.c +?? tmp/ diff --git a/docs/repair/ws-project-v3/README.md b/docs/repair/ws-project-v3/README.md new file mode 100644 index 0000000..3999689 --- /dev/null +++ b/docs/repair/ws-project-v3/README.md @@ -0,0 +1,99 @@ +> 实施阶段之后,用户另行授权更新 PR。提交前审查与补充复跑见 [publication-gate.md](publication-gate.md);下文“不提交”描述原实施阶段边界。 + +# PR #42 v3 本地修复与验收记录 + +本记录是本轮当前结论;ws-operation / ws-control 下的记录是历史输入,不替代这里的源码和测试证据。只完成本地修改、模拟边界测试和独立目录编译,没有提交、推送、更新 PR、设备操作或远端业务执行。 + +## 基线、影响与处理结果 + +当前分支 `fix/v0.5.2-reliability-and-prompts`,HEAD / 审查时 PR head `568b871f64902f88b3c68148ce072eda218fe9db`;PR base `main` / `d6ed947a592265fa12754828bc79803fc50c1db2`。初始已有未跟踪的 output/、tmp/、docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt 不纳入本轮改动。浏览器历史套件按原入口在 output/playwright 输出截图,不清理其中其他文件。 + +- [影响及消息契约](impact-contract.md):先于产品修改建立,补充了实际依赖的 CLI 本地退出。 +- [累计 PR 文件范围](cumulative-files.txt)、[导航/API/服务注册证据](registries.txt):用于确定深入、相邻回归和不修改范围。累计审查侧重实际依赖契约,不是声称逐行证明整个仓库无缺陷。 +- [原始工作区源码与哈希](baseline.json)、baseline.tar.gz:本轮修改前真实 WebUI、SSH 及相关测试。H1 不使用目标分支旧代码作为反例。 +- CLI 原始文件另存 baseline-console.c / baseline-console.json:从同一初始 clean tracked HEAD 导出;它不冒充第一次归档已包含的文件。 +- [实际产品与测试 diff](changes.patch)、[最终输入哈希](final-inputs.json)。v2 operation、TX、订阅管理器、Exec 取消与匹配实现均未修改。 + +| 问题 | 原始证据 | 本轮处理及当前行为 | +|---|---|---| +| H1:请求错误误作 SSH 终态 | baseline-h1.txt/json:实际 C 发帧后生产 JS 退出 SSH,后续 input 不再产生 ssh_input;C op 仍 OPEN | 请求错误只提示本次动作;有效 SSH 不写本地提示符、不自动接管/恢复/重发。真实通道故障走原 operation 唯一终态 | +| 无数据误作 EOF | baseline-no-data.txt:零字节、无 EOF 却结束 Shell 的业务断言 | read/poll/run 使用同一下层判定;暂无数据返回 TIMEOUT 并保持 RUNNING | +| EOF/ERROR 后 close 不释放 | baseline-eof-release.txt:真实 client 销毁后 Shell 包装仍泄漏 | close 消耗所有已分配句柄,不以 RUNNING 作为释放条件;回调至多一次;上层重复清理使用已置空句柄 | +| EAGAIN 无界等待及部分写无明确失败状态 | 原 open/PTY/start/write/resize/close 循环;真实 driver 故障测试 | setup 共用 10 秒预算,write/resize 各 1 秒;部分写记录接受字节,致命/不确定错误标记 ERROR;不重放输入。close 不等远端 EOF,必要时借原 client 本地 disconnect 释放 | +| CLI Ctrl+\\ 退出意图未被循环观察 | baseline-cli-exit.txt:实际 CLI 回调置 console interrupt 后 Shell 仍 active | 该回调请求本地循环退出;保留原 drain-until-no-data 节奏,退出后由原 owner close/destroy;不声称远端已停止 | +| 旧 socket 回调污染新页 / disconnecting 被当终态 | 消费者反向检查及新旧 socket 交错 | 回调、恢复与重连 timer 绑定 socket;连接断开清 SSH 模式;disconnecting 等待真正终态;页面销毁后迟到结果不生效 | + +## 实际修改映射与所有权 + +1. `ts_webui_ws.c`:完整检查 `ssh_request_error` 所有调用点(connect 参数、准入/创建资源失败、统一四控制入口)。这些调用均为请求结果。真正已接受操作的启动/读取/写入故障继续由 `ssh_close` 封口;没有改变公共 request API,也没有修改 operation fallback。IO mutex 外调用关闭和 JSON 编码;原 operation 引用一直保留。 +2. `ts_ssh_shell.c/.h`:统一 read 分类,处理 EOF/ERROR/部分初始化的真实释放;有限等待、部分写计数;增加仅给已串行持有 Shell 的调用方使用的 `request_close`。它只是驱动现有状态上的本地退出,不是第二套操作控制层。分配的 Shell 始终需要 close;close 后不可再次使用旧指针。 +3. `ts_cmd_ssh.c`:唯一新增一行把 Ctrl+\\ 退出传给上述原 Shell,CLI 原清理顺序不变。 +4. `terminal.js`:请求错误、启动失败、会话终态、socket 关闭分别影响对应状态;提示符、恢复和下次输入路由一起适配。固定消息映射只翻译展示,不用于判断生命周期;未识别错误仍保留原始文本。 +5. 中英文语言包、index cache key:启动、请求、观察不完整和远端结果未确认表达一致;仅更新静态资源缓存标识,没有改固件版本、布局或发布流程。 +6. 新测试桥包含整个生产 WS 单元、operation、manager、TX、真正项目 SSH client/Shell。SDK、libssh2、socket、时钟、xterm 渲染为边界替身。CLI 小回调由当前生产文件提取原文字节编译,无手写逻辑副本。历史 adapter 只增加真实下层编译模式和状态查询边界,保留原断言。 + +下层释放依据另外检查了仓库内 libssh2 的 `_libssh2_channel_free` 与 session_free:channel_free 只在 EAGAIN 时保留 channel;其余关闭错误不阻挡 free。项目 client 的本地关闭回调使清理看到断开的传输,随后释放 session/socket。组合测试保留 EAGAIN 时的所有权,未把项目 close/destroy stub 成直接 free。模拟库不证明真实服务器/双核时序。 + +## 可重放验证入口与证据 + +环境:ESP-IDF v5.5.2,ESP32-S3,Apple CommandLineTools;ASan/UBSan 主机 C;Node 和隔离 Chrome。设置 `IDF_PATH` 指向固定 SDK;macOS 测试设置 `DEVELOPER_DIR=/Library/Developer/CommandLineTools`。无需设备或真实 SSH。 + +```sh +python3 tests/ws_subscriptions/replay_project_baseline.py +python3 tests/ws_subscriptions/run_project_v3.py +python3 tests/ws_subscriptions/run_project_v3.py --browser +# 固定 SDK 独立目录 build 后: +V3_BUILD=/tmp/tianshan-project-v3-build/build python3 tests/ws_subscriptions/verify_project_assets.py +V3_BUILD=/tmp/tianshan-project-v3-build/build python3 tests/ws_subscriptions/measure_project_v3.py +# 构建输出消费者: +PROJECT_WEB_ROOT=/tmp/tianshan-project-v3-build/build/esp-idf/ts_webui/web_optimized \ +V3_RESULTS=docs/repair/ws-project-v3/optimized-results \ +python3 tests/ws_subscriptions/run_project_v3.py --browser +``` + +每个套件命令及退出码见 [host.json](results/host.json)、[browser.json](results/browser.json)。runner 保留每个子进程结果并对任一失败返回非零。构建/资源检查是独立入口,不伪装成主机测试。旧缺陷重放返回 0 表示**反例确认**:必须找到指定业务断言,编译失败不算红灯。H1 冻结测试验证同一个 mode/next-input 性质的反面;当前测试增加了后续实际 C 控制,而不是删除旧性质。 + +| 验收链 | 证据与关键断言 | +|---|---| +| C → 实际消息字节 → JS → 下次 C 请求 | results/cross-node-*.json、cross-browser-*.json;unsupported、非法尺寸、可恢复 resize 后合法输入调用原 driver;退出后是 terminal_input,再启动仍成功 | +| 前端真实入口 | Chrome 加载当前 index、语言包、terminal.js;最终 SDK payload 的 bytes 交给真实 ws.onmessage;xterm 渲染和网络替身,不冒充实机浏览器连接 | +| 真实失败和启动拒绝 | 同一桥验证 fatal write、EOF、PTY 启动失败、重复启动和其他页面四类控制;不误伤所有者,不自动重放 | +| 普通终端恢复 | 实际 terminal_stop 后下次 terminal_input 产生 Not a terminal session;实际 JS 生成 terminal_start 回到 C 并成功恢复。SSH 请求错误不触发这条路 | +| 交错及通知失败 | request_error 编码前插入输出+真实关闭;输出在唯一终态之前;编码失败走静态请求提示;直接发送失败不递归报错;输出 HTTPD 入队失败后无需新业务即可结算 | +| 原架构不变量 | operation/adapter/control 日志:G1/G2 原回调/票据,逐目标与引用账本;V1/V2 全 peer 和 exact ID、准备/密钥/连接/认证/提交取消;USER/TIMEOUT/MATCH 分离,观察失败不取消业务 | +| 背压、保护、公平性、事件排空 | host/reviewer/f1_f2 日志:对象/描述符/字节耗尽、目标部分失败、角色日志代次、各主题进展、被选中事件节点保活与排空 | +| 实际下层及停止 | shell_driver.log:真实 open/read/write/poll/run/close/client destroy;部分写、EOF/ERROR、partial init、持续 EAGAIN、两次上层清理;停止 timeout 后 channels 与 op 保留,retry 收尾时无新业务 | +| 相邻依赖 | runtime/certificate/prompts/browser/release 原入口重新执行;配置保存/部分失败/未知、证书和 HTTP 生命周期、导航与表单异步归属等既有行为保持 | +| 编译与运行资源 | build.log、assets.json:真实 www.bin 与验证目录重新生成的 SPIFFS 逐字节相同;JS 语法、gzip 解压一致、cache key 配套;optimized-results 运行构建后的中英文消费者 | + +初次 Chrome 启动及 SDK 配置曾被沙箱权限阻挡;获准本地沙箱外运行后重做成功。开发中的夹具初始化、翻译断言和调度设置失败不计作产品反例,也不替代最终记录。 + +## 资源与性能边界 + +[target-resource.json](target-resource.json) 使用实际目标 compile_commands 的 GCC 及 `-fstack-usage`,分别编译冻结原实现和当前实现。Shell 对象 1076 → 1080 字节(+4),WebUI Shell context 20 → 20。open/poll/resize/统一控制的静态栈帧变化逐项列出;这是单函数静态数值,**不是调用链峰值或实机栈水位**。新增 helper 有自己的调用栈,不能只拿某个函数栈变小推断总栈降低。 + +baseline/current-allocation-metrics.json:相同正常创建、写入、不支持信号、关闭基线,项目分配数依次为 5/0/0/0,最终保留 0。它不计 libssh2 内部真实分配/硬件堆碎片;真实库所有权由边界模型另计 channel/session/socket 并在收尾归零。close 从无界网络等待改为本地收尾,时间上界属于代码与模拟时钟证据,不是设备耗时基准。 + +无新增常驻任务、队列、轮询或采样频率。TX 预算未改,当前 8 连接配置:6 个遥测消息槽/32 描述符,2 个普通消息槽/8 描述符,2 个结果槽/16 描述符,4 个保护转换槽+1 个倒计时槽/40 描述符;共 15 槽/96 描述符。保护字节保留 5×1024=5120;总预算 1 MiB,普通非保护不能借走该保留。单帧、legacy 与重试上限均沿用头文件。请求错误走 HTTPD 请求上下文直接发送,不新增结果预留或永久缓存。所有权、退订及终态释放仍由原 TX/operation 管理。 + +## 消费者反向独立自查 + +按与实施不同的顺序,从下一次用户输入/退出、提示符、恢复、socket 事件、Exec 消费者反查消息生产者及真正下层返回值,并重新查看累计 diff 中共享 API、注册、停止和构建链: + +- 通用 error 在有效 SSH 中只提示请求;普通 terminal 恢复仍由原文义明确的旧契约触发。没有新增“匹配错误文案决定是否关闭”的旁路。 +- 所有已接受 Shell 的真正终态来自原 op;四种页面控制仍经统一完整 peer 获取,不在错误处理后重新查询 current Shell。service owner 入口仍独立。 +- Exec 原创建/取消/输出/业务结束和 timer 收尾未改;共享 client 的已有协作取消通过 runtime/control 回归。 +- 唯一新增控制出口是 CLI 本地循环退出,引用和资源仍由同一 CLI 栈持有,未让回调 close/free 活跃句柄。 +- 未发现本轮已知的高优先级未关闭回归;没有以缺失键数、测试数或编译结果替代上述行为链证据。 + +## 本地结论与未验收事项 + +在记录的 SDK、主机模型和 Chrome 边界内,H1 与本轮直接相关的下层/CLI 缺陷已有反例和当前正向证据,先前有效回归保持,满足本轮**本地交付门槛**;不是可自动合并/发布或实机验收结论。 + +- 未运行设备、真实 SSH/网络、双核抢占压力、实际 CPU/堆碎片/栈水位、TLS 现场握手和长期运行。需设备验收多页面与网络抖动下输入/退出/停止重试、远端部分写及 EOF、连续日志+遥测+保护通知负载、固件/www 更新后的实际缓存刷新。 +- 发送成功不是浏览器 ACK;网络断开或关键通知有限重试耗尽时,不能承诺网页看见每条终态。需重新连接检查,绝不自动重放远端命令。请求错误本身发送失败仅有本地可观测日志,不递归产生通知。 +- 协议仍没有同一连接内的 Shell 操作 ID,无法完全区分同连接跨操作代次的迟到控制;完整 peer 只解决连接实例归属。本轮未偷偷扩展协议。 +- 支持同一构建的 firmware+www,更新后刷新并重连。旧固件仍把 H1 请求错误发成终态,新消费者无法凭旧帧安全猜测真实含义;混合版本不宣称兼容。 +- Chrome 回放使用实际入口与消费者,但 xterm 渲染是边界替身。原套件另测资源加载失败/重试。项目原 xterm CDN 在线依赖仍在,本轮没有新增外部依赖,也不声称完整离线终端验收。 + +CI 后续可接入 host runner、Chrome runner 和固定 SDK artifact checks;本轮未修改 CI 工作流。 diff --git a/docs/repair/ws-project-v3/assets.json b/docs/repair/ws-project-v3/assets.json new file mode 100644 index 0000000..1b51eda --- /dev/null +++ b/docs/repair/ws-project-v3/assets.json @@ -0,0 +1,41 @@ +{ + "index.html": { + "source_sha256": "cb1baa1bfbd2fac00a5fc55caa5442da07ab83b99996af52a41fc5c7e6e98092", + "optimized_sha256": "cb1baa1bfbd2fac00a5fc55caa5442da07ab83b99996af52a41fc5c7e6e98092", + "gzip_sha256": "27ba99dee0cb19ee0bf672ce11bed8e5570cb31b9becd7481717eb97eb794284", + "optimized_bytes": 26703 + }, + "js/terminal.js": { + "source_sha256": "6d93870c3b33b1888388f3a288cfca581a3034a2a212e1e4130853d1aceda581", + "optimized_sha256": "fb42120cf796baf79ad63058838dec0c5044e6fba436c0f86fbd169450240d75", + "gzip_sha256": "4e27a02cbdaa42f128ccb27a1e2a6625b8ce632784858c2385ab0014379b24e8", + "optimized_bytes": 19696 + }, + "js/lang/zh-CN.js": { + "source_sha256": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "optimized_sha256": "81b0fed5b0ac73d51d9c37204c9f62e035a79bbf5b5610d37fc8a936faf9fd64", + "gzip_sha256": "093c3c58b8c5aa1eaf26e50d523da35cc7f6eb84ffba92e72d2db65f7301efa1", + "optimized_bytes": 137314 + }, + "js/lang/en-US.js": { + "source_sha256": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "optimized_sha256": "e9963046086616fecc9ba662df94e736a98c1430865e0caa47292b3690ca0ad0", + "gzip_sha256": "cf8ef5c0dc80f63cc98f09b7e1a5cd558c3576524c9b17b5aa6f00dcb5402fb4", + "optimized_bytes": 143161 + }, + "build": { + "TianShanOS.bin": { + "sha256": "729d2deb703b00ae9264bfdcabba9b63de15437ee34928da21bd799e1dcd27d6", + "bytes": 2183456 + }, + "www.bin": { + "sha256": "3caa18d33014ee7f424295b5643e3526788245998a989db077956672adc26a74", + "bytes": 3145728 + }, + "TianShanOS.elf": { + "sha256": "387099e658e1965919bb7c99a3227d684bdfb42e65ed91e6a0264fafecc9ae11", + "bytes": 18286816 + } + }, + "spiffs_regeneration": "byte-identical from verified optimized directory" +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/baseline-allocation-metrics.json b/docs/repair/ws-project-v3/baseline-allocation-metrics.json new file mode 100644 index 0000000..6d5f009 --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-allocation-metrics.json @@ -0,0 +1 @@ +{"open_allocations":5,"write_allocations":0,"unsupported_allocations":0,"close_allocations":0,"retained":0} diff --git a/docs/repair/ws-project-v3/baseline-cli-exit.txt b/docs/repair/ws-project-v3/baseline-cli-exit.txt new file mode 100644 index 0000000..c7f2f38 --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-cli-exit.txt @@ -0,0 +1,3 @@ +CLI exit: active=1 interrupt=1 +Assertion failed: (!ts_ssh_shell_is_active(shell) && cli_interrupts==1), function main, file test_shell_driver.c, line 27. +tests/ws_subscriptions/run_shell_driver.sh: line 19: 80391 Abort trap: 6 "$build/adapter" "$@" diff --git a/docs/repair/ws-project-v3/baseline-console.c b/docs/repair/ws-project-v3/baseline-console.c new file mode 100644 index 0000000..ebda813 --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-console.c @@ -0,0 +1,1826 @@ +/** + * @file ts_cmd_ssh.c + * @brief SSH Console Commands + * + * 实现 ssh 命令: + * - ssh --host --user --password --exec + * - ssh --test --host --user --password + * - ssh --keygen --type rsa2048 --output /sdcard/id_rsa + * - ssh --keyid 使用安全存储的密钥连接 + * + * 注意:密钥管理已移至独立的 key 命令 + * + * @author TianShanOS Team + * @version 2.0.0 + * @date 2026-01-18 + */ + +#include "ts_console.h" +#include "ts_i18n.h" +#include "ts_api.h" +#include "ts_log.h" +#include "ts_core.h" /* TS_MALLOC_PSRAM, TS_STRDUP_PSRAM */ +#include "ts_ssh_client.h" +#include "ts_ssh_shell.h" +#include "ts_port_forward.h" +#include "ts_crypto.h" +#include "ts_keystore.h" +#include "ts_known_hosts.h" +#include "argtable3/argtable3.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" +#include +#include +#include + +#define TAG "cmd_ssh" + +/*===========================================================================*/ +/* Argument Tables */ +/*===========================================================================*/ + +static struct { + struct arg_str *host; /**< SSH 服务器地址 */ + struct arg_int *port; /**< SSH 端口 (默认 22) */ + struct arg_str *user; /**< 用户名 */ + struct arg_str *password; /**< 密码 */ + struct arg_str *key; /**< 私钥文件路径 (PEM 格式) */ + struct arg_str *keyid; /**< 密钥 ID(从安全存储读取) */ + struct arg_str *exec; /**< 要执行的命令 */ + struct arg_lit *test; /**< 测试连接 */ + struct arg_lit *shell; /**< 交互式 Shell */ + struct arg_str *forward; /**< 端口转发 L:: */ + struct arg_lit *keygen; /**< 生成密钥对 */ + struct arg_lit *copyid; /**< 部署公钥到远程服务器 */ + struct arg_lit *revoke; /**< 从远程服务器撤销公钥 */ + struct arg_str *type; /**< 密钥类型 (rsa2048, rsa4096, ec256, ec384) */ + struct arg_str *output; /**< 密钥输出路径 */ + struct arg_str *comment; /**< 密钥注释 */ + struct arg_int *timeout; /**< 超时时间(秒) */ + struct arg_lit *verbose; /**< 详细输出 */ + struct arg_lit *help; + struct arg_end *end; +} s_ssh_args; + +/*===========================================================================*/ +/* 认证信息结构 */ +/*===========================================================================*/ + +/** + * @brief SSH 认证信息(统一传递认证参数) + * + * 支持三种认证方式: + * 1. 密码认证:只设置 password + * 2. 密钥文件认证:只设置 key_path + * 3. 内存密钥认证:设置 key_data 和 key_len(安全存储密钥) + */ +typedef struct { + const char *password; /**< 密码(密码认证) */ + const char *key_path; /**< 私钥文件路径(文件认证) */ + const uint8_t *key_data; /**< 私钥数据(内存认证,安全存储) */ + size_t key_len; /**< 私钥数据长度 */ + const char *passphrase; /**< 私钥密码(可选) */ +} ssh_auth_info_t; + +/** + * @brief 根据认证信息配置 SSH config + */ +static void config_ssh_auth(ts_ssh_config_t *config, const ssh_auth_info_t *auth) +{ + if (auth->key_data && auth->key_len > 0) { + /* 优先使用内存中的密钥(安全存储) */ + config->auth_method = TS_SSH_AUTH_PUBLICKEY; + config->auth.key.private_key = auth->key_data; + config->auth.key.private_key_len = auth->key_len; + config->auth.key.private_key_path = NULL; + config->auth.key.passphrase = auth->passphrase; + } else if (auth->key_path) { + /* 使用文件路径 */ + config->auth_method = TS_SSH_AUTH_PUBLICKEY; + config->auth.key.private_key_path = auth->key_path; + config->auth.key.private_key = NULL; + config->auth.key.private_key_len = 0; + config->auth.key.passphrase = auth->passphrase; + } else { + /* 密码认证 */ + config->auth_method = TS_SSH_AUTH_PASSWORD; + config->auth.password = auth->password; + } +} + +/*===========================================================================*/ +/* 流式输出回调 */ +/*===========================================================================*/ + +/** 用于传递给回调的上下文 */ +typedef struct { + ts_ssh_session_t session; + bool verbose; +} stream_context_t; + +/** + * @brief Stream output callback for SSH + * @note Reserved for real-time streaming output feature + */ +__attribute__((unused)) +static void stream_output_callback(const char *data, size_t len, bool is_stderr, void *user_data) +{ + stream_context_t *ctx = (stream_context_t *)user_data; + + /* 检查中断请求 */ + if (ts_console_interrupted()) { + ts_ssh_abort(ctx->session); + return; + } + + /* 打印输出 */ + if (is_stderr && ctx->verbose) { + ts_console_printf("\033[31m"); /* 红色表示 stderr */ + } + + /* 直接输出数据 */ + for (size_t i = 0; i < len; i++) { + ts_console_printf("%c", data[i]); + } + + if (is_stderr && ctx->verbose) { + ts_console_printf("\033[0m"); /* 重置颜色 */ + } +} + +/*===========================================================================*/ +/* 主机密钥验证 */ +/*===========================================================================*/ + +/** + * @brief 主机密钥验证提示回调 + * + * 当主机未知或密钥变化时,提示用户确认 + */ +static bool host_verify_prompt(const ts_known_host_t *host, + ts_host_verify_result_t result, + void *user_data) +{ + (void)user_data; + + if (result == TS_HOST_VERIFY_NOT_FOUND) { + ts_console_printf("\n"); + ts_console_printf("┌─────────────────────────────────────────────────────────────┐\n"); + ts_console_printf("│ The authenticity of host '%s' can't be established. \n", host->host); + ts_console_printf("│ %s key fingerprint is: \n", ts_host_key_type_str(host->type)); + ts_console_printf("│ SHA256:%s\n", host->fingerprint); + ts_console_printf("└─────────────────────────────────────────────────────────────┘\n"); + ts_console_printf("\nAre you sure you want to continue connecting? (yes/no): "); + fflush(stdout); + + } else if (result == TS_HOST_VERIFY_MISMATCH) { + ts_console_printf("\n"); + ts_console_printf("╔═══════════════════════════════════════════════════════════════╗\n"); + ts_console_printf("║ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ║\n"); + ts_console_printf("║ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ ║\n"); + ts_console_printf("║ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ║\n"); + ts_console_printf("╠═══════════════════════════════════════════════════════════════╣\n"); + ts_console_printf("║ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! ║\n"); + ts_console_printf("║ Someone could be eavesdropping on you right now ║\n"); + ts_console_printf("║ (man-in-the-middle attack)! ║\n"); + ts_console_printf("╠═══════════════════════════════════════════════════════════════╣\n"); + ts_console_printf("║ Host: %-50s ║\n", host->host); + ts_console_printf("║ New fingerprint: SHA256:%.40s... \n", host->fingerprint); + ts_console_printf("╚═══════════════════════════════════════════════════════════════╝\n"); + ts_console_printf("\nAre you ABSOLUTELY sure you want to continue? (yes/no): "); + fflush(stdout); + } else { + return false; + } + + /* 读取用户输入 */ + char input[16] = {0}; + int idx = 0; + + while (idx < (int)sizeof(input) - 1) { + uint8_t ch; + int len = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, &ch, 1, pdMS_TO_TICKS(30000)); + if (len <= 0) { + ts_console_printf("\nTimeout - aborting connection.\n"); + return false; + } + + if (ch == '\r' || ch == '\n') { + ts_console_printf("\n"); + break; + } else if (ch == 0x03) { /* Ctrl+C */ + ts_console_printf("\n^C\n"); + return false; + } else if (ch == 0x7f || ch == 0x08) { /* Backspace */ + if (idx > 0) { + idx--; + ts_console_printf("\b \b"); + } + } else if (ch >= 32 && ch < 127) { + input[idx++] = ch; + ts_console_printf("%c", ch); + } + } + input[idx] = '\0'; + + if (strcmp(input, "yes") == 0) { + ts_console_printf("Host key accepted and saved.\n\n"); + return true; + } else { + ts_console_printf("Host key verification failed.\n"); + return false; + } +} + +/** + * @brief 验证主机密钥(连接后调用) + * + * @return ESP_OK 验证通过或用户接受,其他表示拒绝 + */ +static esp_err_t verify_host_key(ts_ssh_session_t session, bool verbose) +{ + if (verbose) { + ts_console_printf("Verifying host key...\n"); + } + + esp_err_t ret = ts_known_hosts_verify_interactive(session, host_verify_prompt, NULL); + + if (ret == ESP_OK && verbose) { + ts_console_printf("Host key verified.\n"); + } + + return ret; +} +static esp_err_t cli_verify_before_auth(ts_ssh_session_t session, void *unused) +{ + return verify_host_key(session, false); +} + + +/*===========================================================================*/ +/* Ctrl+C 检测任务 */ +/*===========================================================================*/ + +typedef struct { + ts_ssh_session_t session; + volatile bool running; +} interrupt_monitor_t; + +/** + * @brief Task to monitor Ctrl+C interrupts during SSH sessions + * @note Reserved for async interrupt handling feature + */ +__attribute__((unused)) +static void interrupt_monitor_task(void *arg) +{ + interrupt_monitor_t *mon = (interrupt_monitor_t *)arg; + + while (mon->running) { + /* 非阻塞检查 UART 输入 */ + uint8_t ch; + int len = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, &ch, 1, pdMS_TO_TICKS(50)); + if (len > 0) { + if (ch == 0x03) { /* Ctrl+C = ASCII 0x03 */ + ts_console_printf("\n^C\n"); + ts_console_request_interrupt(); + ts_ssh_abort(mon->session); + break; + } else if (ch == 0x1C) { /* Ctrl+\ = ASCII 0x1C (SIGQUIT) */ + ts_console_printf("\n^\\\n"); + ts_console_request_interrupt(); + ts_ssh_abort(mon->session); + break; + } + } + } + + vTaskDelete(NULL); +} + +/*===========================================================================*/ +/* Command: ssh --exec */ +/*===========================================================================*/ + +static int do_ssh_exec(const char *host, int port, const char *user, + const ssh_auth_info_t *auth, + const char *command, int timeout_sec, bool verbose) +{ + /* 构建 API 参数 */ + cJSON *params = cJSON_CreateObject(); + cJSON_AddStringToObject(params, "host", host); + cJSON_AddNumberToObject(params, "port", port); + cJSON_AddStringToObject(params, "user", user); + cJSON_AddStringToObject(params, "command", command); + cJSON_AddNumberToObject(params, "timeout_ms", timeout_sec * 1000); + + /* 配置认证方式 */ + if (auth->password) { + cJSON_AddStringToObject(params, "password", auth->password); + } else if (auth->key_path) { + cJSON_AddStringToObject(params, "keypath", auth->key_path); + } + /* 注意:keyid 认证需要 CLI 先加载密钥,API 不直接支持 keyid */ + + if (verbose) { + ts_console_printf("Connecting to %s@%s:%d...\n", user, host, port); + ts_console_printf("Executing command: %s\n", command); + ts_console_printf("(Press Ctrl+C to abort)\n\n"); + } + + /* 调用 API */ + ts_api_result_t result; + ts_api_result_init(&result); + + esp_err_t ret = ts_api_call("ssh.exec", params, &result); + cJSON_Delete(params); + + if (ret != ESP_OK || result.code != TS_API_OK) { + ts_console_printf("Error: %s\n", result.message ? result.message : "SSH command failed"); + ts_api_result_free(&result); + return 1; + } + + /* 解析结果 */ + if (result.data) { + cJSON *stdout_obj = cJSON_GetObjectItem(result.data, "stdout"); + cJSON *stderr_obj = cJSON_GetObjectItem(result.data, "stderr"); + cJSON *exit_code = cJSON_GetObjectItem(result.data, "exit_code"); + + /* 输出 stdout */ + if (stdout_obj && cJSON_IsString(stdout_obj) && stdout_obj->valuestring[0]) { + ts_console_printf("%s", stdout_obj->valuestring); + if (stdout_obj->valuestring[strlen(stdout_obj->valuestring)-1] != '\n') { + ts_console_printf("\n"); + } + } + + /* 输出 stderr(红色) */ + if (stderr_obj && cJSON_IsString(stderr_obj) && stderr_obj->valuestring[0]) { + if (verbose) { + ts_console_printf("\033[31m%s\033[0m", stderr_obj->valuestring); + } else { + ts_console_printf("%s", stderr_obj->valuestring); + } + } + + if (verbose && exit_code) { + ts_console_printf("\n--- Command completed with exit code: %d ---\n", + exit_code->valueint); + } + + int code = exit_code ? exit_code->valueint : 0; + ts_api_result_free(&result); + return code; + } + + ts_api_result_free(&result); + return 0; +} + +/*===========================================================================*/ +/* Command: ssh --shell */ +/*===========================================================================*/ + +/** Shell 输出回调 */ +static void shell_output_callback(const char *data, size_t len, void *user_data) +{ + (void)user_data; + /* 直接输出到 stdout,更高效 */ + fwrite(data, 1, len, stdout); + fflush(stdout); /* 立即刷新,确保显示 */ +} + +/** Shell 输入回调 */ +static const char *shell_input_callback(size_t *out_len, void *user_data) +{ + static char input_buf[64]; + ts_ssh_shell_t shell = (ts_ssh_shell_t)user_data; + + *out_len = 0; + + /* 非阻塞读取 UART(0ms 超时 = 立即返回) */ + uint8_t ch; + int len = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, &ch, 1, 0); + if (len > 0) { + /* 检查特殊控制字符 */ + if (ch == 0x03) { /* Ctrl+C */ + /* 发送 SIGINT 到远程 */ + ts_ssh_shell_send_signal(shell, "INT"); + return NULL; + } else if (ch == 0x1C) { /* Ctrl+\ - 退出 Shell */ + ts_console_printf("\n^\\ (Exit shell)\n"); + ts_console_request_interrupt(); + return NULL; + } + + input_buf[0] = ch; + *out_len = 1; + return input_buf; + } + + return NULL; +} + +static int do_ssh_shell(const char *host, int port, const char *user, + const ssh_auth_info_t *auth, + int timeout_sec, bool verbose) +{ + ts_ssh_session_t session = NULL; + ts_ssh_shell_t shell = NULL; + esp_err_t ret; + + /* 配置 SSH 连接 */ + ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); + config.host = host; + config.port = port; + config.username = user; + config.timeout_ms = timeout_sec * 1000; + + /* 配置认证方式 */ + config_ssh_auth(&config, auth); + + if (verbose) { + if (auth->key_data) { + ts_console_printf("Using public key authentication (secure storage)\n"); + } else if (auth->key_path) { + ts_console_printf("Using public key authentication\n"); + } + } + + ts_console_printf("Connecting to %s@%s:%d...\n", user, host, port); + + /* 创建会话 */ + ret = ts_ssh_session_create(&config, &session); + if (ret != ESP_OK) { + ts_console_printf("Error: Failed to create SSH session\n"); + return 1; + } + + /* 连接 */ + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); + if (ret != ESP_OK) { + ts_console_printf("Error: %s\n", ts_ssh_get_error(session)); + ts_ssh_session_destroy(session); + return 1; + } + + /* 验证主机密钥 */ + ret = verify_host_key(session, verbose); + if (ret != ESP_OK) { + ts_console_printf("Error: Host key verification failed\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + return 1; + } + + /* 打开交互式 Shell */ + ts_shell_config_t shell_config = TS_SHELL_DEFAULT_CONFIG(); + shell_config.term_width = 80; + shell_config.term_height = 24; + shell_config.read_timeout_ms = 50; + + ret = ts_ssh_shell_open(session, &shell_config, &shell); + if (ret != ESP_OK) { + ts_console_printf("Error: Failed to open shell\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + return 1; + } + + ts_console_printf("Connected. Interactive shell started.\n"); + ts_console_printf("(Press Ctrl+\\ to exit, Ctrl+C to send SIGINT)\n\n"); + ts_console_clear_interrupt(); + + /* 运行交互式 Shell 循环 */ + ret = ts_ssh_shell_run(shell, shell_output_callback, shell_input_callback, shell); + + int exit_code = ts_ssh_shell_get_exit_code(shell); + + /* 清理 */ + ts_ssh_shell_close(shell); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + ts_console_clear_interrupt(); + + ts_console_printf("\n--- Shell closed (exit code: %d) ---\n", exit_code); + + return (ret == ESP_OK) ? 0 : 1; +} + +/*===========================================================================*/ +/* Command: ssh --forward */ +/*===========================================================================*/ + +static int do_ssh_forward(const char *host, int port, const char *user, + const ssh_auth_info_t *auth, + const char *forward_spec, + int timeout_sec, bool verbose) +{ + ts_ssh_session_t session = NULL; + ts_port_forward_t forward = NULL; + esp_err_t ret; + + (void)verbose; /* 暂未使用 */ + + /* 解析端口转发规格: L:: */ + if (forward_spec[0] != 'L' && forward_spec[0] != 'l') { + ts_console_printf("Error: Forward spec must start with 'L' (local forward)\n"); + ts_console_printf("Format: L::\n"); + ts_console_printf("Example: L8080:localhost:80\n"); + return 1; + } + + int local_port = 0; + char remote_host[128] = {0}; + int remote_port = 0; + + if (sscanf(forward_spec + 1, "%d:%127[^:]:%d", &local_port, remote_host, &remote_port) != 3) { + ts_console_printf("Error: Invalid forward spec format\n"); + ts_console_printf("Format: L::\n"); + ts_console_printf("Example: L8080:localhost:80\n"); + return 1; + } + + if (local_port <= 0 || local_port > 65535 || remote_port <= 0 || remote_port > 65535) { + ts_console_printf("Error: Invalid port number\n"); + return 1; + } + + /* 配置 SSH 连接 */ + ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); + config.host = host; + config.port = port; + config.username = user; + config.timeout_ms = timeout_sec * 1000; + + /* 配置认证方式 */ + config_ssh_auth(&config, auth); + + ts_console_printf("Connecting to %s@%s:%d...\n", user, host, port); + + /* 创建会话 */ + ret = ts_ssh_session_create(&config, &session); + if (ret != ESP_OK) { + ts_console_printf("Error: Failed to create SSH session\n"); + return 1; + } + + /* 连接 */ + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); + if (ret != ESP_OK) { + ts_console_printf("Error: %s\n", ts_ssh_get_error(session)); + ts_ssh_session_destroy(session); + return 1; + } + + /* 验证主机密钥 */ + ret = verify_host_key(session, verbose); + if (ret != ESP_OK) { + ts_console_printf("Error: Host key verification failed\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + return 1; + } + + /* 创建端口转发 */ + ts_forward_config_t fwd_config = TS_FORWARD_DEFAULT_CONFIG(); + fwd_config.direction = TS_FORWARD_LOCAL; + fwd_config.local_host = "0.0.0.0"; /* 允许所有接口访问 */ + fwd_config.local_port = local_port; + fwd_config.remote_host = remote_host; + fwd_config.remote_port = remote_port; + + ret = ts_port_forward_create(session, &fwd_config, &forward); + if (ret != ESP_OK) { + ts_console_printf("Error: Failed to create port forward\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + return 1; + } + + /* 启动转发 */ + ret = ts_port_forward_start(forward); + if (ret != ESP_OK) { + ts_console_printf("Error: Failed to start port forward\n"); + ts_port_forward_destroy(forward); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + return 1; + } + + ts_console_printf("\n"); + ts_console_printf("╔════════════════════════════════════════════╗\n"); + ts_console_printf("║ SSH Port Forwarding Active ║\n"); + ts_console_printf("╠════════════════════════════════════════════╣\n"); + ts_console_printf("║ Local: 0.0.0.0:%-5d ║\n", local_port); + ts_console_printf("║ Remote: %s:%-5d", remote_host, remote_port); + /* 填充空格 */ + int len = strlen(remote_host) + 6; + for (int i = len; i < 25; i++) ts_console_printf(" "); + ts_console_printf("║\n"); + ts_console_printf("╠════════════════════════════════════════════╣\n"); + ts_console_printf("║ Press Ctrl+C to stop forwarding ║\n"); + ts_console_printf("╚════════════════════════════════════════════╝\n\n"); + + ts_console_clear_interrupt(); + + /* 等待用户中断 */ + while (!ts_console_interrupted()) { + /* 检查 UART 输入 */ + uint8_t ch; + int len = uart_read_bytes(CONFIG_ESP_CONSOLE_UART_NUM, &ch, 1, pdMS_TO_TICKS(500)); + if (len > 0 && (ch == 0x03 || ch == 0x1C)) { + ts_console_printf("\n^C\n"); + break; + } + + /* 显示统计(每 5 秒) */ + if (verbose) { + static int counter = 0; + if (++counter >= 10) { + counter = 0; + ts_forward_stats_t stats; + if (ts_port_forward_get_stats(forward, &stats) == ESP_OK) { + ts_console_printf("Stats: %u active, %u total, TX: %llu, RX: %llu\r", + stats.active_connections, stats.total_connections, + stats.bytes_sent, stats.bytes_received); + } + } + } + } + + /* 停止转发 */ + ts_console_printf("Stopping port forward...\n"); + ts_port_forward_stop(forward); + ts_port_forward_destroy(forward); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + ts_console_clear_interrupt(); + + ts_console_printf("Port forwarding stopped.\n"); + return 0; +} + +/*===========================================================================*/ +/* Command: ssh --test */ +/*===========================================================================*/ + +static int do_ssh_test(const char *host, int port, const char *user, + const ssh_auth_info_t *auth, int timeout_sec) +{ + const char *auth_type = "Password"; + if (auth->key_data) { + auth_type = "Public Key (secure storage)"; + } else if (auth->key_path) { + auth_type = "Public Key"; + } + + ts_console_printf("\nSSH Connection Test\n"); + ts_console_printf("═══════════════════════════════════════\n"); + ts_console_printf(" Host: %s\n", host); + ts_console_printf(" Port: %d\n", port); + ts_console_printf(" User: %s\n", user); + ts_console_printf(" Auth: %s\n", auth_type); + ts_console_printf(" Timeout: %d seconds\n", timeout_sec); + ts_console_printf("═══════════════════════════════════════\n\n"); + + /* 构建 API 参数 */ + cJSON *params = cJSON_CreateObject(); + cJSON_AddStringToObject(params, "host", host); + cJSON_AddNumberToObject(params, "port", port); + cJSON_AddStringToObject(params, "user", user); + + /* 配置认证方式 */ + if (auth->password) { + cJSON_AddStringToObject(params, "password", auth->password); + } else if (auth->key_path) { + cJSON_AddStringToObject(params, "keypath", auth->key_path); + } + + ts_console_printf("[1/2] Testing connection... "); + + /* 调用 API */ + ts_api_result_t result; + ts_api_result_init(&result); + + esp_err_t ret = ts_api_call("ssh.test", params, &result); + cJSON_Delete(params); + + if (ret != ESP_OK || result.code != TS_API_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: %s\n", result.message ? result.message : "Connection failed"); + ts_api_result_free(&result); + return 1; + } + + /* 解析结果 */ + bool success = false; + if (result.data) { + cJSON *success_obj = cJSON_GetObjectItem(result.data, "success"); + success = cJSON_IsTrue(success_obj); + + if (!success) { + cJSON *error_obj = cJSON_GetObjectItem(result.data, "error"); + ts_console_printf("FAILED\n"); + if (error_obj && cJSON_IsString(error_obj)) { + ts_console_printf(" Error: %s\n", error_obj->valuestring); + } + } else { + ts_console_printf("OK\n"); + } + } + + ts_api_result_free(&result); + + ts_console_printf("[2/2] Verifying response... "); + if (success) { + ts_console_printf("OK\n"); + } else { + ts_console_printf("FAILED\n"); + } + + ts_console_printf("\n"); + if (success) { + ts_console_printf("✓ SSH connection test PASSED\n"); + return 0; + } else { + ts_console_printf("✗ SSH connection test FAILED\n"); + return 1; + } +} + +/*===========================================================================*/ +/* Command: ssh --copy-id */ +/*===========================================================================*/ + +/** + * @brief 读取公钥文件内容 + */ +static esp_err_t load_public_key(const char *path, char **pubkey_data) +{ + if (!path || !pubkey_data) { + return ESP_ERR_INVALID_ARG; + } + + /* 构建公钥文件路径 (.pub) */ + char pub_path[256]; + snprintf(pub_path, sizeof(pub_path), "%s.pub", path); + + FILE *fp = fopen(pub_path, "r"); + if (!fp) { + ts_console_printf("Error: Cannot open public key file: %s\n", pub_path); + return ESP_ERR_NOT_FOUND; + } + + /* 获取文件大小 */ + fseek(fp, 0, SEEK_END); + long fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (fsize <= 0 || fsize > 8192) { + ts_console_printf("Error: Invalid public key file size: %ld\n", fsize); + fclose(fp); + return ESP_ERR_INVALID_SIZE; + } + + /* 分配内存并读取 */ + char *data = TS_MALLOC_PSRAM(fsize + 1); + if (!data) { + fclose(fp); + return ESP_ERR_NO_MEM; + } + + size_t read_len = fread(data, 1, fsize, fp); + fclose(fp); + + if (read_len != (size_t)fsize) { + free(data); + return ESP_ERR_INVALID_RESPONSE; + } + + /* 去除末尾换行符 */ + data[fsize] = '\0'; + while (fsize > 0 && (data[fsize - 1] == '\n' || data[fsize - 1] == '\r')) { + data[--fsize] = '\0'; + } + + *pubkey_data = data; + return ESP_OK; +} + +static int do_ssh_copy_id(const char *host, int port, const char *user, + const char *password, const char *key_path, + const char *keyid, int timeout_sec) +{ + ts_ssh_session_t session = NULL; + esp_err_t ret; + char *pubkey_data = NULL; + char *privkey_data = NULL; + size_t privkey_len = 0; + bool use_keystore = (keyid != NULL); + + ts_console_printf("\nSSH Public Key Deployment\n"); + ts_console_printf("═══════════════════════════════════════\n"); + ts_console_printf(" Host: %s\n", host); + ts_console_printf(" Port: %d\n", port); + ts_console_printf(" User: %s\n", user); + if (use_keystore) { + ts_console_printf(" Key: [secure storage] %s\n", keyid); + } else { + ts_console_printf(" Key: %s.pub\n", key_path); + } + ts_console_printf("═══════════════════════════════════════\n\n"); + + /* 读取公钥 */ + ts_console_printf("[1/4] Reading public key... "); + if (use_keystore) { + size_t pubkey_len = 0; + ret = ts_keystore_load_public_key(keyid, &pubkey_data, &pubkey_len); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: Cannot load public key '%s' from secure storage\n", keyid); + return 1; + } + } else { + ret = load_public_key(key_path, &pubkey_data); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + return 1; + } + } + ts_console_printf("OK\n"); + + /* 配置 SSH 连接(使用密码认证) */ + ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); + config.host = host; + config.port = port; + config.username = user; + config.timeout_ms = timeout_sec * 1000; + config.auth_method = TS_SSH_AUTH_PASSWORD; + config.auth.password = password; + + ts_console_printf("[2/4] Connecting with password... "); + ret = ts_ssh_session_create(&config, &session); + if (ret != ESP_OK) { + ts_console_printf("FAILED (session create)\n"); + free(pubkey_data); + return 1; + } + + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: %s\n", ts_ssh_get_error(session)); + ts_ssh_session_destroy(session); + free(pubkey_data); + return 1; + } + + /* 验证主机密钥 */ + ret = verify_host_key(session, false); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Host key verification failed\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + return 1; + } + ts_console_printf("OK\n"); + + /* 构建部署命令 */ + ts_console_printf("[3/4] Deploying public key... "); + + /* 命令:创建 .ssh 目录并追加公钥到 authorized_keys */ + char *deploy_cmd = TS_MALLOC_PSRAM(strlen(pubkey_data) + 512); + if (!deploy_cmd) { + ts_console_printf("FAILED (out of memory)\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + return 1; + } + + snprintf(deploy_cmd, strlen(pubkey_data) + 512, + "mkdir -p ~/.ssh && chmod 700 ~/.ssh && " + "echo '%s' >> ~/.ssh/authorized_keys && " + "chmod 600 ~/.ssh/authorized_keys && " + "echo 'Key deployed successfully'", + pubkey_data); + + ts_ssh_exec_result_t result; + ret = ts_ssh_exec(session, deploy_cmd, &result); + free(deploy_cmd); + + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: %s\n", ts_ssh_get_error(session)); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + return 1; + } + + bool deploy_ok = (result.exit_code == 0); + if (result.stderr_data && strlen(result.stderr_data) > 0) { + ts_console_printf("WARNING\n"); + ts_console_printf(" stderr: %s\n", result.stderr_data); + } else if (deploy_ok) { + ts_console_printf("OK\n"); + } else { + ts_console_printf("FAILED (exit code: %d)\n", result.exit_code); + } + ts_ssh_exec_result_free(&result); + + /* 断开密码连接 */ + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + + if (!deploy_ok) { + free(pubkey_data); + return 1; + } + + /* 验证公钥认证 */ + ts_console_printf("[4/4] Verifying public key auth... "); + + /* 加载私钥用于验证 */ + if (use_keystore) { + ret = ts_keystore_load_private_key(keyid, &privkey_data, &privkey_len); + if (ret != ESP_OK) { + ts_console_printf("SKIPPED\n"); + ts_console_printf(" Note: Cannot load private key for verification\n"); + free(pubkey_data); + ts_console_printf("\n✓ Public key deployed successfully!\n"); + ts_console_printf("\nYou can now connect without password:\n"); + ts_console_printf(" ssh --host %s --user %s --keyid %s --shell\n", host, user, keyid); + return 0; + } + } + + /* 使用公钥认证重新连接 */ + ts_ssh_config_t verify_config = TS_SSH_DEFAULT_CONFIG(); + verify_config.host = host; + verify_config.port = port; + verify_config.username = user; + verify_config.timeout_ms = timeout_sec * 1000; + verify_config.auth_method = TS_SSH_AUTH_PUBLICKEY; + + /* 配置认证方式 */ + if (use_keystore && privkey_data) { + /* 使用内存中的密钥(安全,不写入临时文件) */ + verify_config.auth.key.private_key = (const uint8_t *)privkey_data; + verify_config.auth.key.private_key_len = privkey_len; + verify_config.auth.key.private_key_path = NULL; + } else { + /* 使用文件路径 */ + verify_config.auth.key.private_key_path = key_path; + verify_config.auth.key.private_key = NULL; + verify_config.auth.key.private_key_len = 0; + } + verify_config.auth.key.passphrase = NULL; + + ret = ts_ssh_session_create(&verify_config, &session); + if (ret != ESP_OK) { + ts_console_printf("FAILED (session)\n"); + free(pubkey_data); + if (privkey_data) { + memset(privkey_data, 0, privkey_len); /* 安全清零 */ + free(privkey_data); + } + return 1; + } + + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); + + if (ret != ESP_OK) { + const char *error_msg = ts_ssh_get_error(session); + + /* 检查是否是密钥类型不支持的错误 */ + if (error_msg && (strstr(error_msg, "Key type not supported") || + strstr(error_msg, "Method unimplemented") || + strstr(error_msg, "Method not supported"))) { + ts_console_printf("SKIPPED\n"); + ts_console_printf(" Note: Key type may not be fully supported for verification\n"); + ts_ssh_session_destroy(session); + free(pubkey_data); + if (privkey_data) { + memset(privkey_data, 0, privkey_len); + free(privkey_data); + } + ts_console_printf("\n✓ Public key deployed successfully!\n"); + ts_console_printf("\n⚠ Verification skipped (may be ECDSA or memory auth limitation)\n"); + ts_console_printf(" The key has been added to authorized_keys.\n"); + ts_console_printf(" Try connecting with:\n"); + if (use_keystore) { + ts_console_printf(" ssh --host %s --user %s --keyid %s --shell\n", host, user, keyid); + } else { + ts_console_printf(" ssh --host %s --user %s --key %s --shell\n", host, user, key_path); + } + return 0; + } + + /* 检查是否是 ECDSA 不支持 */ + if (privkey_data && strstr(privkey_data, "BEGIN EC PRIVATE KEY")) { + ts_console_printf("SKIPPED\n"); + ts_console_printf(" Note: ECDSA keys may not be fully supported by libssh2 mbedTLS backend\n"); + ts_ssh_session_destroy(session); + free(pubkey_data); + memset(privkey_data, 0, privkey_len); + free(privkey_data); + ts_console_printf("\n✓ Public key deployed successfully!\n"); + ts_console_printf("\nYou can now connect. If authentication fails, try using RSA keys:\n"); + ts_console_printf(" key --generate --id mykey --type rsa\n"); + return 0; + } + + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: %s\n", error_msg ? error_msg : "Unknown error"); + ts_ssh_session_destroy(session); + free(pubkey_data); + if (privkey_data) { + memset(privkey_data, 0, privkey_len); + free(privkey_data); + } + ts_console_printf("\n⚠ Key deployed but verification failed\n"); + return 1; + } + + ts_console_printf("OK\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + if (privkey_data) { + memset(privkey_data, 0, privkey_len); + free(privkey_data); + } + + ts_console_printf("\n✓ Public key authentication configured successfully!\n"); + ts_console_printf("\nYou can now connect without password:\n"); + if (use_keystore) { + ts_console_printf(" ssh --host %s --user %s --keyid %s --shell\n", host, user, keyid); + } else { + ts_console_printf(" ssh --host %s --user %s --key %s --shell\n", host, user, key_path); + } + + return 0; +} + +/*===========================================================================*/ +/* Command: ssh --revoke */ +/*===========================================================================*/ + +/** + * @brief 从远程服务器撤销已部署的公钥 + * + * 使用密码认证连接到远程服务器,然后从 authorized_keys 中移除匹配的公钥。 + * 支持两种方式指定要撤销的密钥: + * 1. --keyid:从安全存储获取公钥 + * 2. --key:从文件读取公钥 + * + * @param host 远程主机地址 + * @param port SSH 端口 + * @param user 用户名 + * @param password 密码(用于认证) + * @param key_path 私钥文件路径(用于定位公钥) + * @param keyid 密钥 ID(从安全存储) + * @param timeout_sec 超时时间(秒) + * @return 0 成功,非 0 失败 + */ +static int do_ssh_revoke(const char *host, int port, const char *user, + const char *password, const char *key_path, + const char *keyid, int timeout_sec) +{ + ts_console_printf("\n══════════════════════════════════════════════════════════════════\n"); + ts_console_printf(" SSH Public Key Revocation\n"); + ts_console_printf("══════════════════════════════════════════════════════════════════\n\n"); + + ts_ssh_session_t session = NULL; + esp_err_t ret; + char *pubkey_data = NULL; + size_t pubkey_len = 0; + bool use_keystore = (keyid != NULL && key_path == NULL); + + /* 获取公钥数据(用于匹配要删除的密钥) */ + if (use_keystore) { + ts_console_printf("Loading public key '%s' from secure storage... ", keyid); + ret = ts_keystore_load_public_key(keyid, &pubkey_data, &pubkey_len); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Failed to load public key: %s\n", esp_err_to_name(ret)); + return 1; + } + ts_console_printf("OK\n"); + } else { + /* 从文件读取公钥 */ + char pubkey_path[256]; + snprintf(pubkey_path, sizeof(pubkey_path), "%s.pub", key_path); + + ts_console_printf("Reading public key from %s... ", pubkey_path); + + FILE *f = fopen(pubkey_path, "r"); + if (!f) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Cannot open public key file\n"); + return 1; + } + + fseek(f, 0, SEEK_END); + pubkey_len = ftell(f); + fseek(f, 0, SEEK_SET); + + pubkey_data = TS_MALLOC_PSRAM(pubkey_len + 1); + if (!pubkey_data) { + fclose(f); + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Memory allocation failed\n"); + return 1; + } + + fread(pubkey_data, 1, pubkey_len, f); + fclose(f); + pubkey_data[pubkey_len] = '\0'; + ts_console_printf("OK\n"); + } + + /* 提取公钥的 key type 和 key data 部分(忽略 comment) + * 格式: "ssh-rsa AAAAB3Nza... comment" + * 我们需要 "ssh-rsa AAAAB3Nza..." 部分来匹配 */ + char *key_type = NULL; + char *key_data = NULL; + char *pubkey_copy = TS_STRDUP_PSRAM(pubkey_data); + if (!pubkey_copy) { + free(pubkey_data); + ts_console_printf("Error: Memory allocation failed\n"); + return 1; + } + + /* 解析公钥格式 */ + key_type = strtok(pubkey_copy, " "); + key_data = strtok(NULL, " "); + + if (!key_type || !key_data) { + ts_console_printf("Error: Invalid public key format\n"); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + + ts_console_printf("\nKey to revoke:\n"); + ts_console_printf(" Type: %s\n", key_type); + ts_console_printf(" Data: %.40s...\n", key_data); + + /* 显示警告 */ + ts_console_printf("\n"); + ts_console_printf("┌─────────────────────────────────────────────────────────────┐\n"); + ts_console_printf("│ WARNING: This will remove the public key from the remote │\n"); + ts_console_printf("│ server's authorized_keys file. │\n"); + ts_console_printf("└─────────────────────────────────────────────────────────────┘\n"); + ts_console_printf("\nTarget: %s@%s:%d\n\n", user, host, port); + + /* 配置 SSH 连接(使用密码认证) */ + ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); + config.host = host; + config.port = port; + config.username = user; + config.timeout_ms = timeout_sec * 1000; + config.auth_method = TS_SSH_AUTH_PASSWORD; + config.auth.password = password; + + /* 创建会话 */ + ts_console_printf("Connecting with password authentication... "); + ret = ts_ssh_session_create(&config, &session); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Failed to create SSH session\n"); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + + /* 连接 */ + ret = ts_ssh_connect_with_verifier(session, cli_verify_before_auth, NULL); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: %s\n", ts_ssh_get_error(session)); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + ts_console_printf("OK\n"); + + /* 验证主机密钥 */ + ret = verify_host_key(session, false); + if (ret != ESP_OK) { + ts_console_printf(" Host key verification failed\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + + /* 构建检查命令 - 使用 grep -F 进行固定字符串匹配 + * 只取 key_data 的前 100 字符作为匹配特征,避免命令行过长 + * 同时需要检查完整密钥类型前缀以确保唯一性 */ + char key_signature[128]; + size_t sig_len = strlen(key_data) > 100 ? 100 : strlen(key_data); + snprintf(key_signature, sizeof(key_signature), "%s %.*s", key_type, (int)sig_len, key_data); + + char cmd[1024]; + snprintf(cmd, sizeof(cmd), + "if [ -f ~/.ssh/authorized_keys ]; then " + " grep -cF '%s' ~/.ssh/authorized_keys 2>/dev/null || echo '0'; " + "else " + " echo '0'; " + "fi", + key_signature); + + /* 先检查密钥是否存在 */ + ts_console_printf("Checking if key exists on remote... "); + + ts_ssh_exec_result_t result; + ret = ts_ssh_exec(session, cmd, &result); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Failed to check key: %s\n", ts_ssh_get_error(session)); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + + int key_count = 0; + if (result.stdout_data) { + key_count = atoi(result.stdout_data); + } + ts_ssh_exec_result_free(&result); + + if (key_count == 0) { + ts_console_printf("NOT FOUND\n"); + ts_console_printf("\n⚠ The specified public key was not found on the remote server.\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + return 0; /* 不视为错误 */ + } + + ts_console_printf("FOUND (%d match%s)\n", key_count, key_count > 1 ? "es" : ""); + + /* 执行删除操作 - 使用 grep -vF 进行固定字符串排除 */ + ts_console_printf("Removing key from authorized_keys... "); + + snprintf(cmd, sizeof(cmd), + "cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.bak 2>/dev/null; " + "grep -vF '%s' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp 2>/dev/null && " + "mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys && " + "chmod 600 ~/.ssh/authorized_keys && " + "echo 'OK'", + key_signature); + + ret = ts_ssh_exec(session, cmd, &result); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Failed to remove key: %s\n", ts_ssh_get_error(session)); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + + bool remove_ok = (result.stdout_data && strstr(result.stdout_data, "OK") != NULL); + ts_ssh_exec_result_free(&result); + + if (!remove_ok) { + ts_console_printf("FAILED\n"); + ts_console_printf("Error: Failed to remove key\n"); + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + return 1; + } + ts_console_printf("OK\n"); + + /* 验证删除成功 */ + ts_console_printf("Verifying removal... "); + + snprintf(cmd, sizeof(cmd), + "grep -cF '%s' ~/.ssh/authorized_keys 2>/dev/null || echo '0'", + key_signature); + + ret = ts_ssh_exec(session, cmd, &result); + if (ret == ESP_OK && result.stdout_data) { + int remaining = atoi(result.stdout_data); + if (remaining == 0) { + ts_console_printf("OK\n"); + } else { + ts_console_printf("WARNING (%d keys still match)\n", remaining); + } + } else { + ts_console_printf("SKIPPED\n"); + } + ts_ssh_exec_result_free(&result); + + ts_ssh_disconnect(session); + ts_ssh_session_destroy(session); + free(pubkey_data); + free(pubkey_copy); + + ts_console_printf("\n✓ Public key revoked successfully!\n"); + ts_console_printf("\n A backup was saved to ~/.ssh/authorized_keys.bak on the remote server.\n"); + + /* 如果是 keystore 密钥,提示可以删除本地密钥 */ + if (use_keystore) { + ts_console_printf("\n To also delete the local key:\n"); + ts_console_printf(" key --delete --id %s\n", keyid); + } + + return 0; +} + +/*===========================================================================*/ +/* Command: ssh --keygen */ +/*===========================================================================*/ + +/** + * @brief 解析密钥类型字符串 + */ +static bool parse_key_type(const char *type_str, ts_crypto_key_type_t *type) +{ + if (!type_str || !type) return false; + + if (strcmp(type_str, "rsa2048") == 0 || strcmp(type_str, "rsa") == 0) { + *type = TS_CRYPTO_KEY_RSA_2048; + return true; + } else if (strcmp(type_str, "rsa4096") == 0) { + *type = TS_CRYPTO_KEY_RSA_4096; + return true; + } else if (strcmp(type_str, "ec256") == 0 || strcmp(type_str, "ecdsa") == 0) { + *type = TS_CRYPTO_KEY_EC_P256; + return true; + } else if (strcmp(type_str, "ec384") == 0) { + *type = TS_CRYPTO_KEY_EC_P384; + return true; + } + return false; +} + +/** + * @brief 获取密钥类型的描述字符串 + */ +static const char *get_key_type_desc(ts_crypto_key_type_t type) +{ + switch (type) { + case TS_CRYPTO_KEY_RSA_2048: return "RSA 2048-bit"; + case TS_CRYPTO_KEY_RSA_4096: return "RSA 4096-bit"; + case TS_CRYPTO_KEY_EC_P256: return "ECDSA P-256 (secp256r1)"; + case TS_CRYPTO_KEY_EC_P384: return "ECDSA P-384 (secp384r1)"; + default: return "Unknown"; + } +} + +/*===========================================================================*/ +/* Command: ssh --keygen (file-based) */ +/*===========================================================================*/ + +/** + * @brief 生成密钥对到文件(保留直接实现,因为需要写入文件系统) + * + * 注意:如果要生成到安全存储,应使用 key 命令或 ssh.keygen API + */ +static int do_ssh_keygen(const char *type_str, const char *output_path, const char *comment) +{ + ts_crypto_key_type_t key_type; + ts_keypair_t keypair = NULL; + esp_err_t ret; + + /* 解析密钥类型 */ + if (!parse_key_type(type_str, &key_type)) { + ts_console_printf("Error: Invalid key type '%s'\n", type_str); + ts_console_printf("Supported types: rsa, rsa2048, rsa4096, ecdsa, ec256, ec384\n"); + return 1; + } + + ts_console_printf("\nSSH Key Generation\n"); + ts_console_printf("═══════════════════════════════════════\n"); + ts_console_printf(" Type: %s\n", get_key_type_desc(key_type)); + ts_console_printf(" Output: %s\n", output_path); + if (comment) { + ts_console_printf(" Comment: %s\n", comment); + } + ts_console_printf("═══════════════════════════════════════\n\n"); + + /* 生成密钥对 */ + ts_console_printf("[1/4] Generating key pair... "); + + /* RSA 4096 需要较长时间,给出提示 */ + if (key_type == TS_CRYPTO_KEY_RSA_4096) { + ts_console_printf("(this may take 30-60 seconds)\n "); + } + + ret = ts_crypto_keypair_generate(key_type, &keypair); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: Failed to generate key pair (%s)\n", esp_err_to_name(ret)); + return 1; + } + ts_console_printf("OK\n"); + + /* 导出私钥 (PEM 格式) */ + ts_console_printf("[2/4] Saving private key... "); + + char *private_pem = TS_MALLOC_PSRAM(8192); + if (!private_pem) { + ts_console_printf("FAILED (out of memory)\n"); + ts_crypto_keypair_free(keypair); + return 1; + } + + size_t pem_len = 8192; + ret = ts_crypto_keypair_export_private(keypair, private_pem, &pem_len); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + free(private_pem); + ts_crypto_keypair_free(keypair); + return 1; + } + + /* 写入私钥文件 */ + FILE *fp = fopen(output_path, "w"); + if (!fp) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: Cannot create file %s\n", output_path); + free(private_pem); + ts_crypto_keypair_free(keypair); + return 1; + } + + fprintf(fp, "%s", private_pem); + fclose(fp); + free(private_pem); + ts_console_printf("OK\n"); + + /* 导出公钥 (OpenSSH 格式) */ + ts_console_printf("[3/4] Saving public key... "); + + char *openssh_pub = TS_MALLOC_PSRAM(4096); + if (!openssh_pub) { + ts_console_printf("FAILED (out of memory)\n"); + ts_crypto_keypair_free(keypair); + return 1; + } + + size_t openssh_len = 4096; + const char *key_comment = comment ? comment : "TianShanOS-generated-key"; + ret = ts_crypto_keypair_export_openssh(keypair, openssh_pub, &openssh_len, key_comment); + if (ret != ESP_OK) { + ts_console_printf("FAILED\n"); + free(openssh_pub); + ts_crypto_keypair_free(keypair); + return 1; + } + + /* 写入公钥文件 (.pub) */ + char pub_path[256]; + snprintf(pub_path, sizeof(pub_path), "%s.pub", output_path); + + fp = fopen(pub_path, "w"); + if (!fp) { + ts_console_printf("FAILED\n"); + ts_console_printf(" Error: Cannot create file %s\n", pub_path); + free(openssh_pub); + ts_crypto_keypair_free(keypair); + return 1; + } + + fprintf(fp, "%s", openssh_pub); + fclose(fp); + ts_console_printf("OK\n"); + + /* 显示公钥指纹 */ + ts_console_printf("[4/4] Key generation complete!\n\n"); + + ts_console_printf("Files created:\n"); + ts_console_printf(" Private key: %s\n", output_path); + ts_console_printf(" Public key: %s\n", pub_path); + ts_console_printf("\nPublic key (for authorized_keys):\n"); + ts_console_printf("─────────────────────────────────────────\n"); + ts_console_printf("%s", openssh_pub); + ts_console_printf("─────────────────────────────────────────\n"); + + ts_console_printf("\nUsage:\n"); + ts_console_printf(" 1. Copy the public key above to remote server's ~/.ssh/authorized_keys\n"); + ts_console_printf(" 2. Use: ssh --host --user --key %s --exec \n", output_path); + + free(openssh_pub); + ts_crypto_keypair_free(keypair); + + return 0; +} + +/*===========================================================================*/ +/* Command Handler */ +/*===========================================================================*/ + +static int ssh_cmd_handler(int argc, char **argv) +{ + /* 解析参数 */ + int nerrors = arg_parse(argc, argv, (void **)&s_ssh_args); + + /* 显示帮助 */ + if (s_ssh_args.help->count > 0) { + ts_console_printf("\n%s\n\n", TS_STR(TS_STR_SSH_HELP_USAGE)); + ts_console_printf("%s\n\n", TS_STR(TS_STR_SSH_HELP_DESC)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_CONN_OPTS)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_HOST)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_PORT)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_USER)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_PASSWORD)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_KEY)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_KEYID)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EXEC)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_SHELL)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_FORWARD)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_TEST)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_TIMEOUT)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_VERBOSE)); + ts_console_printf("\n%s\n", TS_STR(TS_STR_SSH_HELP_KEY_MGMT)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_KEYGEN)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_COPYID)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_REVOKE)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_TYPE)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_OUTPUT)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_COMMENT)); + ts_console_printf("\n%s\n", TS_STR(TS_STR_SSH_HELP_GENERAL)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_HELP_OPT)); + ts_console_printf("\n%s\n", TS_STR(TS_STR_SSH_HELP_EXAMPLES)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_KEYGEN)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_KEYGEN_CMD)); + ts_console_printf(" \n"); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_STORED)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_KEY_LIST)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_KEY_GEN)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_SSH)); + ts_console_printf(" \n"); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_COPYID)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_COPYID_CMD)); + ts_console_printf(" \n"); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_REVOKE)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_REVOKE_CMD)); + ts_console_printf(" \n"); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_FILE)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_EX_FILE_CMD)); + ts_console_printf("\n%s\n", TS_STR(TS_STR_SSH_HELP_NOTE)); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_NOTE_HOSTS)); + return 0; + } + + /* 参数错误检查 */ + if (nerrors > 0) { + arg_print_errors(stderr, s_ssh_args.end, "ssh"); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_USE)); + return 1; + } + + /* 检查是否是密钥生成模式 */ + if (s_ssh_args.keygen->count > 0) { + /* --keygen 模式:必须指定 --type 和 --output */ + if (s_ssh_args.type->count == 0) { + ts_console_printf("Error: --type is required for key generation\n"); + ts_console_printf("Supported types: rsa, rsa2048, rsa4096, ecdsa, ec256, ec384\n"); + return 1; + } + if (s_ssh_args.output->count == 0) { + ts_console_printf("Error: --output is required for key generation\n"); + ts_console_printf("Example: --output /sdcard/id_rsa\n"); + return 1; + } + + const char *comment = (s_ssh_args.comment->count > 0) ? s_ssh_args.comment->sval[0] : NULL; + return do_ssh_keygen(s_ssh_args.type->sval[0], s_ssh_args.output->sval[0], comment); + } + + /* 检查是否是公钥部署模式 */ + if (s_ssh_args.copyid->count > 0) { + /* --copyid 模式:必须指定 --host, --user, --password, 以及 --key 或 --keyid */ + if (s_ssh_args.host->count == 0) { + ts_console_printf("Error: --host is required for --copyid\n"); + return 1; + } + if (s_ssh_args.user->count == 0) { + ts_console_printf("Error: --user is required for --copyid\n"); + return 1; + } + if (s_ssh_args.password->count == 0) { + ts_console_printf("Error: --password is required for --copyid (initial auth)\n"); + return 1; + } + if (s_ssh_args.key->count == 0 && s_ssh_args.keyid->count == 0) { + ts_console_printf("Error: --key or --keyid is required for --copyid\n"); + ts_console_printf(" --key Use key file (public key at .pub)\n"); + ts_console_printf(" --keyid Use key from secure storage\n"); + return 1; + } + + int port = (s_ssh_args.port->count > 0) ? s_ssh_args.port->ival[0] : 22; + int timeout = (s_ssh_args.timeout->count > 0) ? s_ssh_args.timeout->ival[0] : 10; + const char *key_path = (s_ssh_args.key->count > 0) ? s_ssh_args.key->sval[0] : NULL; + const char *keyid = (s_ssh_args.keyid->count > 0) ? s_ssh_args.keyid->sval[0] : NULL; + + return do_ssh_copy_id(s_ssh_args.host->sval[0], port, + s_ssh_args.user->sval[0], s_ssh_args.password->sval[0], + key_path, keyid, timeout); + } + + /* 检查是否是公钥撤销模式 */ + if (s_ssh_args.revoke->count > 0) { + /* --revoke 模式:必须指定 --host, --user, --password, 以及 --key 或 --keyid */ + if (s_ssh_args.host->count == 0) { + ts_console_printf("Error: --host is required for --revoke\n"); + return 1; + } + if (s_ssh_args.user->count == 0) { + ts_console_printf("Error: --user is required for --revoke\n"); + return 1; + } + if (s_ssh_args.password->count == 0) { + ts_console_printf("Error: --password is required for --revoke (auth to remove key)\n"); + return 1; + } + if (s_ssh_args.key->count == 0 && s_ssh_args.keyid->count == 0) { + ts_console_printf("Error: --key or --keyid is required for --revoke\n"); + ts_console_printf(" --key Revoke key file (public key at .pub)\n"); + ts_console_printf(" --keyid Revoke key from secure storage\n"); + return 1; + } + + int port = (s_ssh_args.port->count > 0) ? s_ssh_args.port->ival[0] : 22; + int timeout = (s_ssh_args.timeout->count > 0) ? s_ssh_args.timeout->ival[0] : 10; + const char *key_path = (s_ssh_args.key->count > 0) ? s_ssh_args.key->sval[0] : NULL; + const char *keyid = (s_ssh_args.keyid->count > 0) ? s_ssh_args.keyid->sval[0] : NULL; + + return do_ssh_revoke(s_ssh_args.host->sval[0], port, + s_ssh_args.user->sval[0], s_ssh_args.password->sval[0], + key_path, keyid, timeout); + } + + /* 连接模式:必需参数检查 */ + if (s_ssh_args.host->count == 0) { + ts_console_printf("Error: --host is required\n"); + return 1;; + } + + if (s_ssh_args.user->count == 0) { + ts_console_printf("Error: --user is required\n"); + return 1; + } + + /* 认证方式检查:必须提供 password、key 或 keyid 之一 */ + if (s_ssh_args.password->count == 0 && s_ssh_args.key->count == 0 && s_ssh_args.keyid->count == 0) { + ts_console_printf("Error: --password, --key, or --keyid is required\n"); + return 1; + } + + /* 获取参数值 */ + const char *host = s_ssh_args.host->sval[0]; + int port = (s_ssh_args.port->count > 0) ? s_ssh_args.port->ival[0] : 22; + const char *user = s_ssh_args.user->sval[0]; + const char *password = (s_ssh_args.password->count > 0) ? s_ssh_args.password->sval[0] : NULL; + const char *key_path = (s_ssh_args.key->count > 0) ? s_ssh_args.key->sval[0] : NULL; + const char *keyid = (s_ssh_args.keyid->count > 0) ? s_ssh_args.keyid->sval[0] : NULL; + int timeout = (s_ssh_args.timeout->count > 0) ? s_ssh_args.timeout->ival[0] : 10; + bool verbose = (s_ssh_args.verbose->count > 0); + + /* 构建认证信息 */ + ssh_auth_info_t auth = {0}; + char *loaded_key_data = NULL; + size_t loaded_key_len = 0; + + if (keyid && !key_path) { + /* 从安全存储加载密钥到内存(不写入临时文件) */ + if (verbose) { + ts_console_printf("Loading key '%s' from secure storage...\n", keyid); + } + + esp_err_t ret = ts_keystore_load_private_key(keyid, &loaded_key_data, &loaded_key_len); + if (ret != ESP_OK) { + ts_console_printf("Error: Failed to load key '%s' from secure storage (%s)\n", + keyid, esp_err_to_name(ret)); + return 1; + } + + /* 使用内存中的密钥(不暴露到文件系统) */ + auth.key_data = (const uint8_t *)loaded_key_data; + auth.key_len = loaded_key_len; + auth.passphrase = NULL; /* TODO: 支持加密密钥 */ + + if (verbose) { + ts_console_printf("Key loaded: %zu bytes\n", loaded_key_len); + /* 显示密钥类型 */ + if (strstr(loaded_key_data, "BEGIN RSA PRIVATE KEY")) { + ts_console_printf("Key type: RSA (PKCS#1)\n"); + } else if (strstr(loaded_key_data, "BEGIN EC PRIVATE KEY")) { + ts_console_printf("Key type: ECDSA\n"); + ts_console_printf(" Warning: ECDSA key authentication from memory may not work\n"); + ts_console_printf(" with libssh2 mbedTLS backend. Use RSA keys if possible.\n"); + } + } + } else if (key_path) { + /* 使用文件路径 */ + auth.key_path = key_path; + auth.passphrase = NULL; + } else { + /* 密码认证 */ + auth.password = password; + } + + int result = 0; + + /* 执行操作(按优先级) */ + if (s_ssh_args.shell->count > 0) { + /* 交互式 Shell */ + result = do_ssh_shell(host, port, user, &auth, timeout, verbose); + } else if (s_ssh_args.forward->count > 0) { + /* 端口转发 */ + result = do_ssh_forward(host, port, user, &auth, + s_ssh_args.forward->sval[0], timeout, verbose); + } else if (s_ssh_args.exec->count > 0) { + /* 执行命令 */ + const char *command = s_ssh_args.exec->sval[0]; + result = do_ssh_exec(host, port, user, &auth, command, timeout, verbose); + } else if (s_ssh_args.test->count > 0) { + /* 测试连接 */ + result = do_ssh_test(host, port, user, &auth, timeout); + } else { + ts_console_printf("Error: Specify --exec, --shell, --forward, --test, or --keygen\n"); + ts_console_printf("%s\n", TS_STR(TS_STR_SSH_HELP_USE)); + result = 1; + } + + /* 清理内存中的密钥数据 */ + if (loaded_key_data) { + /* 安全清零内存 */ + memset(loaded_key_data, 0, loaded_key_len); + free(loaded_key_data); + } + + return result; +} + +/*===========================================================================*/ +/* Command Registration */ +/*===========================================================================*/ + +esp_err_t ts_cmd_ssh_register(void) +{ + /* 连接相关参数 */ + s_ssh_args.host = arg_str0(NULL, "host", "", "Remote host address"); + s_ssh_args.port = arg_int0(NULL, "port", "", "SSH port (default: 22)"); + s_ssh_args.user = arg_str0(NULL, "user", "", "Username"); + s_ssh_args.password = arg_str0(NULL, "password", "", "Password"); + s_ssh_args.key = arg_str0(NULL, "key", "", "Private key file (PEM)"); + s_ssh_args.keyid = arg_str0(NULL, "keyid", "", "Key ID from secure storage"); + s_ssh_args.exec = arg_str0(NULL, "exec", "", "Command to execute"); + s_ssh_args.test = arg_lit0(NULL, "test", "Test SSH connection"); + s_ssh_args.shell = arg_lit0(NULL, "shell", "Open interactive shell"); + s_ssh_args.forward = arg_str0(NULL, "forward", "", "Port forward: L::"); + s_ssh_args.timeout = arg_int0(NULL, "timeout", "", "Timeout in seconds"); + s_ssh_args.verbose = arg_lit0("v", "verbose", "Verbose output"); + + /* 密钥生成参数 */ + s_ssh_args.keygen = arg_lit0(NULL, "keygen", "Generate SSH key pair"); + s_ssh_args.copyid = arg_lit0(NULL, "copyid", "Deploy public key to remote server"); + s_ssh_args.revoke = arg_lit0(NULL, "revoke", "Remove public key from remote server"); + s_ssh_args.type = arg_str0(NULL, "type", "", "Key type: rsa, rsa2048, rsa4096, ecdsa, ec256, ec384"); + s_ssh_args.output = arg_str0(NULL, "output", "", "Output file path for private key"); + s_ssh_args.comment = arg_str0(NULL, "comment", "", "Comment for the public key"); + + /* 通用参数 */ + s_ssh_args.help = arg_lit0("h", "help", "Show help"); + s_ssh_args.end = arg_end(10); + + /* 注册命令 */ + const esp_console_cmd_t cmd = { + .command = "ssh", + .help = "SSH client. Use 'ssh --help' for details. Key management: use 'key' command.", + .hint = NULL, + .func = ssh_cmd_handler, + .argtable = &s_ssh_args, + }; + + esp_err_t ret = esp_console_cmd_register(&cmd); + if (ret != ESP_OK) { + TS_LOGE(TAG, "Failed to register ssh command: %s", esp_err_to_name(ret)); + } else { + TS_LOGI(TAG, "Registered command: ssh"); + } + + return ret; +} diff --git a/docs/repair/ws-project-v3/baseline-console.json b/docs/repair/ws-project-v3/baseline-console.json new file mode 100644 index 0000000..b92c640 --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-console.json @@ -0,0 +1,5 @@ +{ + "source": "git show 568b871:components/ts_console/commands/ts_cmd_ssh.c", + "basis": "initial workspace was clean for tracked files", + "sha256": "4b4edc6e2be0dfedda745d998232bafe99e12496d2ddb8af9f4bb04a5a1bb526" +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/baseline-eof-release.txt b/docs/repair/ws-project-v3/baseline-eof-release.txt new file mode 100644 index 0000000..bdfd9ca --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-eof-release.txt @@ -0,0 +1,3 @@ +EOF ledger: allocations=1 channels=0 sessions=0 sockets=0 +Assertion failed: (!live_allocations && !driver_channels && !driver_sessions && !driver_sockets), function empty, file test_shell_driver.c, line 22. +tests/ws_subscriptions/run_shell_driver.sh: line 19: 80371 Abort trap: 6 "$build/adapter" "$@" diff --git a/docs/repair/ws-project-v3/baseline-fixture.tar.gz b/docs/repair/ws-project-v3/baseline-fixture.tar.gz new file mode 100644 index 0000000..619a6c4 Binary files /dev/null and b/docs/repair/ws-project-v3/baseline-fixture.tar.gz differ diff --git a/docs/repair/ws-project-v3/baseline-h1.json b/docs/repair/ws-project-v3/baseline-h1.json new file mode 100644 index 0000000..32d3112 --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-h1.json @@ -0,0 +1,88 @@ +{ + "recovered": false, + "next": { + "type": "terminal_input", + "data": "x" + }, + "state": { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1 + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1 + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1 + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH control could not be completed for this session" + }, + "fd": 1 + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1 + }, + { + "finished": true + } + ] +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/baseline-h1.txt b/docs/repair/ws-project-v3/baseline-h1.txt new file mode 100644 index 0000000..0e9856d --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-h1.txt @@ -0,0 +1 @@ +CONFIRMED H1: actual C request error leaves op OPEN but JS exits SSH and next input is not routed to SSH diff --git a/docs/repair/ws-project-v3/baseline-no-data.txt b/docs/repair/ws-project-v3/baseline-no-data.txt new file mode 100644 index 0000000..621be9a --- /dev/null +++ b/docs/repair/ws-project-v3/baseline-no-data.txt @@ -0,0 +1,2 @@ +Assertion failed: (ts_ssh_shell_read(shell,buf,sizeof(buf),&n)==ESP_ERR_TIMEOUT && ts_ssh_shell_is_active(shell)), function main, file test_shell_driver.c, line 30. +tests/ws_subscriptions/run_shell_driver.sh: line 19: 80350 Abort trap: 6 "$build/adapter" "$@" diff --git a/docs/repair/ws-project-v3/baseline.json b/docs/repair/ws-project-v3/baseline.json new file mode 100644 index 0000000..a26cd34 --- /dev/null +++ b/docs/repair/ws-project-v3/baseline.json @@ -0,0 +1,121 @@ +{ + "head": "568b871f64902f88b3c68148ce072eda218fe9db", + "pr_base": "d6ed947a592265fa12754828bc79803fc50c1db2", + "status": "?? docs/repair/ws-project-v3/\n?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt\n?? output/\n?? tmp/\n", + "sha256": { + "components/ts_webui/CMakeLists.txt": "53e02258893758d55edf0debef2e0694b154ecccda65ab3b5bb5d34770c39d45", + "components/ts_webui/Kconfig": "6a1fc77d34f7c635b44a922f4c7c9fb96832a9f6bb433967c26e3bdc451ae286", + "components/ts_webui/web/favicon.ico": "1ea04b690d7fe816da5efb405c13f9cd953366026eb3553e214de8d5df0d3648", + "components/ts_webui/web/index.html": "0b3ce77c7da2da7d18bd086dfe55fc33e994adbfe06f2f47eb6d69c01fe6124a", + "components/ts_webui/include/ts_ws_subscriptions.h": "edcfedcdb48cc47bdd776218d43f362f4f2feb84f0a8bd347b465e3dd751e3ae", + "components/ts_webui/include/ts_ws_transport.h": "4c7b996ed4e6a578ce7daa1a02a13729795bd4dca2e66eb8b49895b6f59f36ee", + "components/ts_webui/include/ts_ws_operation.h": "4a31681f9e5d0041d2627b5850b23c083e1b0ca3b876acf959adab5955611512", + "components/ts_webui/include/ts_webui.h": "374e230b4f0d016adb2373acd2e6431cf537eaeb8f7f84efcf53523d6dad0402", + "components/ts_webui/src/ts_webui_ws.c": "8f26c8ddf9bf391a70ec0909809e2a084352f4cff23c97875baecd838e4eb4ba", + "components/ts_webui/src/ts_ws_transport.c": "e2eaeb31d00d7996a84badc669ca5587628c63b044c9a8014e587e84b5ab37f8", + "components/ts_webui/src/ts_ws_operation.c": "504ce5caa9375a792692eec681a86bf4515aa5c2d28e758d67df08117b6fe865", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_api.c": "c8225f3fc36be3446947e205932a3d43340665d687b81c23c16556f3be8dc9b8", + "components/ts_webui/src/ts_ws_subscriptions.c": "9f8d2f33a374d6992a1ef119cd20a791244e44abc8d7cd66dc906b4896f764fb", + "components/ts_webui/web/css/style.css": "30dab8799ed2a8b0a5da49ec84202b30f3c951779ea4533e847a53b2ac9b8dff", + "components/ts_webui/web/images/tslogo-32.png": "64e4bce72f2b13c81bef5b46ae919abeeb47f98571cf5e55460385880731810b", + "components/ts_webui/web/images/tslogo-512.png": "b7508585c46e16fcc7d42c52459ab55df32716aea85a10a560cd64de7cceb8e8", + "components/ts_webui/web/images/tslogo-128.png": "f09ac97789726872277a0399338cd9bfd0493752de930aeb6b2c6f7b0a864c3b", + "components/ts_webui/web/images/README.md": "f4429665c315cdabc2a935caf0f1423632dd7cbff84f34914965969217102237", + "components/ts_webui/web/images/tslogo-48.png": "41f959e327dca63386a2f254b8a245a6fa151904a06eae93ae6c449277467f70", + "components/ts_webui/web/images/tslogo-256.png": "55dc7df59429c23fdc531baba002b7b23f5a4f2be0f29b2ecc5098f3df059da7", + "components/ts_webui/web/images/tslogo-64.png": "a0809405c5632eb4bf1f1b4783175c2b92b25fc522f5b0682a35d3cfa1c58752", + "components/ts_webui/web/images/favicon.icns": "bdc873fa7bff5e1888d80273f99f22d97d3719d4b17419e68e64eafd85c2b039", + "components/ts_webui/web/images/tslogo-original.png": "9fb0ee8532c2d572d8b235f7586d225f00609cf8defb98b59cf55ae749e83ed1", + "components/ts_webui/web/js/terminal.js": "048ca0d64b9ee52b0c2b4f3f3f7e270a2bbd35fc729dbd513cc7b11dfb26bbcf", + "components/ts_webui/web/js/router.js": "1e73ca3bf272a54aea8c516809e09e10f257b620bf66311bbbe358693fe377d5", + "components/ts_webui/web/js/dragSort.js": "7c5b9159cb8bb88b35222424db6d8bd822d3960899d5c090c17955700d6590af", + "components/ts_webui/web/js/api.js": "6fb266abb3780a0d402d86ad95a3644b8e1f488136ad44dc18ddd83caaa8dab4", + "components/ts_webui/web/js/i18n.js": "2eed1c54b4ef89bc2e4221a3fd900e88bd8d7a11064a04d97dcc3decfdeedbd8", + "components/ts_webui/web/js/app.js": "ad63a38112eab45af87da091f3536156614db526bb85f2c83bafa7867439230b", + "components/ts_webui/web/fonts/remixicon.woff2": "e92dc38bfb1d15dbb9d9ca9e645754f68e7c5b224e33c45a17048bd0cf2407a6", + "components/ts_webui/web/fonts/remixicon.css": "b2218eec4e02513f0feef46f74f13c852152f54eafd83d1274057e3895f0ea1c", + "components/ts_webui/web/js/lang/en-US.js": "24bfe60afe5589d5f257baa6b1ef66f23e23453f70be9c8bd7778944f73ac3fc", + "components/ts_webui/web/js/lang/zh-CN.js": "0ec109e51f3bc21531f8fca829eaed271898a4cfd7172696881013d5b20e6817", + "components/ts_security/CMakeLists.txt": "cdc8e21b6985899e65385ce4b2c92958cc540f19f3445255301b20ad71241c88", + "components/ts_security/Kconfig": "c3d0036c138f0bf227f73558802a24892694e5f8328ecda2ab8007e0aa219a06", + "components/ts_security/include/ts_ssh_service.h": "73fbddabe3eaed6a191b90b1644eb50eb440509723c92f4a61788c2306596102", + "components/ts_security/include/ts_known_hosts.h": "4b1244556d046e0057ba0d372498f92d263e43183975d5e55d0bbaea669b0934", + "components/ts_security/include/ts_ssh_log_watch.h": "08677f37f9ee0a3620f6ed38770c4f1977d3b70787e96e57db0f934de5c5452f", + "components/ts_security/include/ts_crypto.h": "371ac3b950f7185eaa21a710c4e823ed806ab337d573cfffdcfe58656aeee8c0", + "components/ts_security/include/ts_ssh_shell.h": "19a5f9706d3db36baa967f5ecefb77735e3771ac176e2e680a89be342f39c8e1", + "components/ts_security/include/ts_scp.h": "5801a44ef598560d9eef3265ec5b891b494e2682b3049834d3694abe0f86f175", + "components/ts_security/include/ts_ssh_commands_config.h": "d1fa1bbc2762bc4accf697db09959396cb5d82bb67ba1806a0cd4f9b45305352", + "components/ts_security/include/ts_ssh_probe.h": "697c24c0ff5244397d3483997357a81311cbd24b718d64b845efd96e19979e43", + "components/ts_security/include/ts_keystore.h": "55831771c42ae32640dc6ce1d7755f3487149f71f42d1f1ca7451af2ff675f40", + "components/ts_security/include/ts_sftp.h": "6d0c9ab1ac7dd3eab5d820798f543be18e2de1d43028dc72ca088b3ec13ab1fe", + "components/ts_security/include/ts_security.h": "01cf0f2c1ee2599c0d733ac5d7466e73358fe5483aad23d654c2e6b99c039f35", + "components/ts_security/include/ts_ssh_client.h": "ceb00ed29965279a154e061638b58769e148ea370f5435de48c90c1c8d90f928", + "components/ts_security/include/ts_ssh_hosts_config.h": "48d27c0cdeb6b0f462d41eaef281b6f2afe6e460b810a61f2f98278d0609280d", + "components/ts_security/include/ts_port_forward.h": "a249f758369a81a7db44f71e4aed0511cd4f5aa932cc4bde33b29c393b5d39be", + "components/ts_security/src/ts_ssh_client.c": "071b875b4029cc9d0d9e5538ce7a05921a07ec57d09faa45d295fccb7625552d", + "components/ts_security/src/ts_security.c": "1c4bd91f4ab676be0739b60b826e026a84baade609369995c845b1991a1e2c49", + "components/ts_security/src/ts_port_forward.c": "b2dafd8ffc849f684cf0a9f332864876951d2d9ee7fd8a69ce7704430d00853f", + "components/ts_security/src/ts_ssh_hosts_config.c": "36d70ff90bef5b0efdf1195c614a33a70b7ed521807c28a2a3b4d918265b2056", + "components/ts_security/src/ts_known_hosts.c": "72e2c0c5723cf9fed7c589e46152b5806c4bdcfba565b862305d2fb299ec3844", + "components/ts_security/src/ts_ssh_log_watch.c": "3843930a4337ea56092d37e1ade0651dd1f6a14c3f5596d33bc83a7880712f6b", + "components/ts_security/src/ts_auth.c": "b4456d19bb701f5be50c08bb8024c8b24eb97820fd47c72c9fda6e1ff334b78d", + "components/ts_security/src/ts_ssh_service.c": "fc345627f4f2c9417dd0e74fb47b3d77e2cc9f41fd9537bd2f633b0260e5e01c", + "components/ts_security/src/ts_scp.c": "cf328d792705cf8d6b00ecc3b8369ae8360fba977a3147e0a2eef6634a08cff8", + "components/ts_security/src/ts_ssh_shell.c": "9e696a8daee19df9b1caf76e3170ed89ae45a1139b6ca60544221f3ba27d22b1", + "components/ts_security/src/ts_crypto.c": "5ef1140c4f122a49a531de1bff5c48c80067bdcadf2139553c35a59fd5404587", + "components/ts_security/src/ts_ssh_probe.c": "810b235d84659426a3181ec594a345e2fd0ac7fc7c1ce765c34265ad1bc05843", + "components/ts_security/src/ts_ssh_commands_config.c": "f12fdb5169de9e52db02590bf9d821bc08291b6c24e62f4f81bc54b03574e6da", + "components/ts_security/src/ts_sftp.c": "e05a3cd229dcf4344cfcc785755e075b52f94a4276411abbbfb6e7716793a899", + "components/ts_security/src/ts_keystore.c": "0046e9a9f13a4dd73f932a2861b787c6264ad1597694b3cdc8a9b9eca251ea1d", + "tests/ws_subscriptions/test_init.c": "49b7ade237c4fe5df5fe683f4ec731c222cc4939b91b19d976471e99d29173c7", + "tests/ws_subscriptions/test_operation.c": "c28fd00d191f92bbe8722033a3dbf5d7c6bcc54e054c06acff4429fce149a4e6", + "tests/ws_subscriptions/run_reviewer.sh": "2a957bb5d4e0ca0c357ec32fffb23aa60c75019b60cc4c5c33d468d389013ea8", + "tests/ws_subscriptions/test_control.c": "7e70ad841a86f6c39a1274f715502991e37c7aa1b7802f7b3dcf805a6aa7d917", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/test_manager.c": "a1b46f3ad3a877a5cfd1235e7253418aec965c442a5c21ab811a68f1e70be8cd", + "tests/ws_subscriptions/test_f1_f2.c": "7d4907e42f3a9c7110055acb6ca667abd62a5f16712306c7dde6b85ec285c9b4", + "tests/ws_subscriptions/replay_control_baseline.py": "aefd5ff8bc6ced036c9fec466bef70bddb8b66949b4eed3994cdd109fe2f255f", + "tests/ws_subscriptions/test_reviewer.c": "65916f6af7fb3fe00d00bf6999a55f441422b35d4d95b3f801d9cb9b0f591c54", + "tests/ws_subscriptions/test_reviewer_service.c": "3fa82db0882b90d69450ddcd7a50e5904ae60e2cab8e62ea11656ac4c21e2890", + "tests/ws_subscriptions/README.md": "e2a186d0cc38c5a2df86207cde9f371365b95e678908b15943a7556fe57e5ada", + "tests/ws_subscriptions/test_operation_adapter.c": "4178c7dd1b9ad582cdc0fd5950dced82d448494494702dfd30246d7ba60f3338", + "tests/ws_subscriptions/run_operation_adapter.sh": "1a5b900b4c6aae1619b86a285b6371a683263304db90a81d82477d8fb750d3f5", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/run_reviewer_baseline.sh": "6ea73543f64c6de65f59480300cf2d73ece85b798a7a430df5b55f2adae1bb96", + "tests/ws_subscriptions/replay_operation_baseline.py": "ba26a739d9dfb4b30b4e10ac0b3955994738820b85a156406dcaaa9518382cc3", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_reviewer_core.c": "7669567ad82171ae32102779e4fc98c4b88871f9e9f761600a21623378882ef2", + "tests/ws_subscriptions/run_control.sh": "e2853acc8652b99dfccca85d25425b870996e7bfcb03a5cfe021b76e66d0139e", + "tests/ws_subscriptions/run_operation.sh": "bf9d6db03b483d4b74db26e464efc73b673648ef82565edf987e6f275c9ee6c5", + "tests/ws_subscriptions/run_f1_f2.sh": "8e804b7a5c66663a62da53f9027b175722034e5cce77ba152aba8ad13b527935", + "tests/ws_subscriptions/test_reviewer_http.c": "2b9696ac9dd86be96db383392d3bcf61f81a5ab2e881933d767aad8f91d30c00", + "tests/ws_subscriptions/baseline_operation_adapter.c": "0b0703b144fa8fc7d412110e55b4d7d2010196e9422deb78ff00185059a5af05", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_console.h": "f97fca9ebf2a497277d9ac5af3581a2e83789b4acf3e8b125e0f36fb27210151", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "de005401b26f9dce9028db4bbc656ea72e55730535769be4ddf31ccec072c2dc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/timers.h": "fd6abec4a547b6e9caed8f0514a08ead4223303736dade89179bb8812a2a5d94", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/prompts/ownership.browser.test.cjs": "1938411e7cc76ecc190b3469c58e58fd8aaa4a080ede60989190b4abd1147903", + "tests/prompts/browser.test.cjs": "59e7f77387e015d7d8b3ed926750f1fbf6328059d52b82bb79cbf973b590a1aa", + "tests/prompts/README.md": "ae4c5e8cca1dae0c7ec4e54d51b58977a6e15a743fdedc32215111ddc4bd5b13", + "tests/prompts/harness.cjs": "7c176507bb17c57abf22d73c5399b34cd8e221fb9663c4e5efe7ac3d168f944a", + "tests/prompts/package-lock.json": "8bef9925fb843348d3bf83eea1953314108e97f1db9c5972f4e8bf6741269a7a", + "tests/prompts/package.json": "180e0ffb285f1258b7a87ba2688e88c7c454ad7a4de3a9c56daa4c5346a7eae1", + "tests/prompts/static.test.cjs": "e8a08a747786a84efc6b976545e6d929ec3cf40278c0166b9bdb6b7a8fa810fe", + "tests/prompts/regression.test.cjs": "c372b74e125b361103defe66017c3eeb286fea9975cf4f3167ed5cf981050516" + } +} diff --git a/docs/repair/ws-project-v3/baseline.tar.gz b/docs/repair/ws-project-v3/baseline.tar.gz new file mode 100644 index 0000000..48aec35 Binary files /dev/null and b/docs/repair/ws-project-v3/baseline.tar.gz differ diff --git a/docs/repair/ws-project-v3/build.log b/docs/repair/ws-project-v3/build.log new file mode 100644 index 0000000..babceb3 --- /dev/null +++ b/docs/repair/ws-project-v3/build.log @@ -0,0 +1,30 @@ +Executing action: all (aliases: build) +Running ninja in directory /private/tmp/tianshan-project-v3-build/build +Executing "ninja all"... +[1/10] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-project-v3-build/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-project-v3-build/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[2/10] No install step for 'bootloader' +[3/10] cd /tmp/tianshan-project-v3-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-project-v3-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-project-v3-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[4/10] Completed 'bootloader' +[5/10] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_shell.c.obj +[6/10] Linking C static library esp-idf/ts_security/libts_security.a +[7/10] Generating esp-idf/esp_system/ld/sections.ld +[8/10] Linking CXX executable TianShanOS.elf +[9/10] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-project-v3-build/build/TianShanOS.bin +[10/10] cd /tmp/tianshan-project-v3-build/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-project-v3-build/build/partition_table/partition-table.bin /tmp/tianshan-project-v3-build/build/TianShanOS.bin +TianShanOS.bin binary size 0x215120 bytes. Smallest app partition is 0x300000 bytes. 0xeaee0 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-project-v3-build/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-project-v3-build/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-project-v3-build/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-project-v3-build/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-project-v3-build/build/www.bin +or from the "/private/tmp/tianshan-project-v3-build/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ws-project-v3/changes.patch b/docs/repair/ws-project-v3/changes.patch new file mode 100644 index 0000000..19406bc --- /dev/null +++ b/docs/repair/ws-project-v3/changes.patch @@ -0,0 +1,1396 @@ +diff --git a/components/ts_console/commands/ts_cmd_ssh.c b/components/ts_console/commands/ts_cmd_ssh.c +index ebda813..0a0b5a1 100644 +--- a/components/ts_console/commands/ts_cmd_ssh.c ++++ b/components/ts_console/commands/ts_cmd_ssh.c +@@ -412,6 +412,7 @@ static const char *shell_input_callback(size_t *out_len, void *user_data) + } else if (ch == 0x1C) { /* Ctrl+\ - 退出 Shell */ + ts_console_printf("\n^\\ (Exit shell)\n"); + ts_console_request_interrupt(); ++ ts_ssh_shell_request_close(shell); + return NULL; + } + +diff --git a/components/ts_security/include/ts_ssh_shell.h b/components/ts_security/include/ts_ssh_shell.h +index 8af5053..f88efa0 100644 +--- a/components/ts_security/include/ts_ssh_shell.h ++++ b/components/ts_security/include/ts_ssh_shell.h +@@ -95,20 +95,28 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + ts_ssh_shell_t *shell_out); + + /** +- * @brief Close the shell session ++ * @brief Consume and release an allocated Shell handle, including EOF/ERROR. ++ * Caller must clear its handle; a second call with a freed pointer is invalid. ++ * If channel release would block, locally disconnect its owning SSH session. ++ * This does not confirm that remote processes have terminated. + * + * @param shell Shell handle + * @return esp_err_t ESP_OK on success + */ + esp_err_t ts_ssh_shell_close(ts_ssh_shell_t shell); + ++/** Request local loop exit without freeing the handle or confirming remote exit. ++ * The caller serializes this with other Shell access and still calls close(). */ ++esp_err_t ts_ssh_shell_request_close(ts_ssh_shell_t shell); ++ + /** + * @brief Write data to the shell (send to remote) + * + * @param shell Shell handle + * @param data Data to write + * @param len Length of data +- * @param written Pointer to receive bytes written (optional) ++ * @param written Bytes accepted by the transport, including partial failure (optional). ++ * Write/setup waits are bounded; timeout leaves ERROR and must not be replayed. + * @return esp_err_t ESP_OK on success + */ + esp_err_t ts_ssh_shell_write(ts_ssh_shell_t shell, +diff --git a/components/ts_security/src/ts_ssh_shell.c b/components/ts_security/src/ts_ssh_shell.c +index 08f8444..a2e8b16 100644 +--- a/components/ts_security/src/ts_ssh_shell.c ++++ b/components/ts_security/src/ts_ssh_shell.c +@@ -13,6 +13,7 @@ + #include "ts_ssh_client.h" + #include "ts_core.h" /* TS_CALLOC_PSRAM */ + #include "esp_log.h" ++#include "esp_timer.h" + #include "freertos/FreeRTOS.h" + #include "freertos/task.h" + #include "freertos/semphr.h" +@@ -38,6 +39,7 @@ struct ts_ssh_shell_s { + LIBSSH2_CHANNEL *channel; /**< SSH 通道 */ + ts_shell_config_t config; /**< Shell 配置 */ + ts_shell_state_t state; /**< 当前状态 */ ++ bool close_notified; + int exit_code; /**< 退出码 */ + + /* 回调 */ +@@ -102,6 +104,30 @@ static int wait_socket(int sock, LIBSSH2_SESSION *session, int timeout_ms) + return select(sock + 1, readfd, writefd, NULL, &timeout); + } + ++/* A libssh2 request left in EAGAIN cannot be replaced by a different request. ++ * Bound the wait and retire the channel on uncertainty instead of replaying. */ ++static bool shell_wait(int sock,LIBSSH2_SESSION *ssh,int64_t deadline) ++{ ++ int64_t left=deadline-esp_timer_get_time(); ++ if(left<=0)return false; ++ int ms=(int)((left+999)/1000);if(ms>100)ms=100; ++ return wait_socket(sock,ssh,ms)>=0 && esp_timer_get_time()channel)return; ++ /* libssh2 retains ownership only on EAGAIN. Its session owns that channel ++ * and the client's local-disconnect callbacks make destruction nonwaiting. */ ++ if(libssh2_channel_free(shell->channel)==LIBSSH2_ERROR_EAGAIN) ++ ts_ssh_disconnect(shell->ssh_session); ++ shell->channel=NULL; ++} ++static void shell_notify_close(ts_ssh_shell_t shell) ++{ ++ if(!shell->close_notified){shell->close_notified=true; ++ if(shell->close_cb)shell->close_cb(shell->exit_code,shell->close_cb_data);} ++} ++ + /* ============================================================================ + * 公开 API 实现 + * ============================================================================ */ +@@ -114,6 +140,7 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + return ESP_ERR_INVALID_ARG; + } + ++ *shell_out=NULL; + if (!ts_ssh_is_connected(session)) { + ESP_LOGE(TAG, "SSH session not connected"); + return ESP_ERR_INVALID_STATE; +@@ -154,10 +181,11 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + /* 打开通道 */ + LIBSSH2_CHANNEL *channel = NULL; + int rc; ++ int64_t deadline=esp_timer_get_time()+10000000; + + while ((channel = libssh2_channel_open_session(ssh)) == NULL && + libssh2_session_last_errno(ssh) == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 1000); ++ if(!shell_wait(sock,ssh,deadline))goto setup_timeout; + } + + if (!channel) { +@@ -168,6 +196,7 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + return ESP_FAIL; + } + ++ shell->channel=channel; + /* 请求 PTY */ + const char *term = get_term_string(shell->config.term_type); + +@@ -177,14 +206,14 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + shell->config.term_width, + shell->config.term_height, + 0, 0)) == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 1000); ++ if(!shell_wait(sock,ssh,deadline))goto setup_timeout; + } + + if (rc != 0) { + char *err_msg = NULL; + libssh2_session_last_error(ssh, &err_msg, NULL, 0); + ESP_LOGE(TAG, "Failed to request PTY: %s", err_msg ? err_msg : "unknown"); +- libssh2_channel_free(channel); ++ shell_release_channel(shell); + free(shell); + return ESP_FAIL; + } +@@ -194,14 +223,14 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + + /* 启动 Shell */ + while ((rc = libssh2_channel_shell(channel)) == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 1000); ++ if(!shell_wait(sock,ssh,deadline))goto setup_timeout; + } + + if (rc != 0) { + char *err_msg = NULL; + libssh2_session_last_error(ssh, &err_msg, NULL, 0); + ESP_LOGE(TAG, "Failed to start shell: %s", err_msg ? err_msg : "unknown"); +- libssh2_channel_free(channel); ++ shell_release_channel(shell); + free(shell); + return ESP_FAIL; + } +@@ -212,6 +241,18 @@ esp_err_t ts_ssh_shell_open(ts_ssh_session_t session, + *shell_out = shell; + ESP_LOGI(TAG, "Interactive shell opened"); + return ESP_OK; ++setup_timeout: ++ shell_release_channel(shell); ++ ts_ssh_disconnect(session); /* pending open/setup must not survive as a usable session */ ++ free(shell); ++ return ESP_ERR_TIMEOUT; ++} ++ ++esp_err_t ts_ssh_shell_request_close(ts_ssh_shell_t shell) ++{ ++ if (!shell) return ESP_ERR_INVALID_ARG; ++ if (shell->state == TS_SHELL_STATE_RUNNING) shell->state = TS_SHELL_STATE_CLOSED; ++ return ESP_OK; + } + + esp_err_t ts_ssh_shell_close(ts_ssh_shell_t shell) +@@ -220,117 +261,51 @@ esp_err_t ts_ssh_shell_close(ts_ssh_shell_t shell) + return ESP_ERR_INVALID_ARG; + } + +- if (shell->state != TS_SHELL_STATE_RUNNING) { +- return ESP_OK; +- } +- +- LIBSSH2_SESSION *ssh = ts_ssh_get_libssh2_session(shell->ssh_session); +- int sock = ts_ssh_get_socket(shell->ssh_session); +- +- /* 发送 EOF */ +- int rc; +- while ((rc = libssh2_channel_send_eof(shell->channel)) == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 100); +- } +- +- /* 等待远程关闭 */ +- while ((rc = libssh2_channel_wait_eof(shell->channel)) == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 100); +- } +- +- /* 关闭通道 */ +- while ((rc = libssh2_channel_close(shell->channel)) == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 100); +- } +- +- /* 获取退出码 */ +- if (rc == 0) { +- shell->exit_code = libssh2_channel_get_exit_status(shell->channel); +- } +- +- /* 调用关闭回调 */ +- if (shell->close_cb) { +- shell->close_cb(shell->exit_code, shell->close_cb_data); +- } +- +- libssh2_channel_free(shell->channel); +- shell->channel = NULL; +- shell->state = TS_SHELL_STATE_CLOSED; +- +- ESP_LOGI(TAG, "Shell closed with exit code: %d", shell->exit_code); +- +- /* 释放结构 */ ++ /* EOF/ERROR changes state, not ownership. All allocated handles are ++ * consumed here; callers clear their handle after this call. */ ++ if(shell->channel && shell->state==TS_SHELL_STATE_RUNNING) ++ shell->exit_code=libssh2_channel_get_exit_status(shell->channel); ++ shell->state=TS_SHELL_STATE_CLOSED; ++ shell_release_channel(shell); ++ shell_notify_close(shell); + free(shell); + return ESP_OK; + } + +-esp_err_t ts_ssh_shell_write(ts_ssh_shell_t shell, +- const char *data, size_t len, +- size_t *written) ++esp_err_t ts_ssh_shell_write(ts_ssh_shell_t shell,const char *data,size_t len,size_t *written) + { +- if (!shell || !data || len == 0) { +- return ESP_ERR_INVALID_ARG; +- } +- +- if (shell->state != TS_SHELL_STATE_RUNNING) { +- return ESP_ERR_INVALID_STATE; +- } +- +- LIBSSH2_SESSION *ssh = ts_ssh_get_libssh2_session(shell->ssh_session); +- int sock = ts_ssh_get_socket(shell->ssh_session); +- +- size_t total_written = 0; +- while (total_written < len) { +- int rc = libssh2_channel_write(shell->channel, data + total_written, +- len - total_written); +- if (rc > 0) { +- total_written += rc; +- } else if (rc == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 100); +- } else { +- ESP_LOGE(TAG, "Write error: %d", rc); +- return ESP_FAIL; +- } +- } +- +- if (written) { +- *written = total_written; ++ if(written)*written=0; ++ if(!shell || !data || !len)return ESP_ERR_INVALID_ARG; ++ if(shell->state!=TS_SHELL_STATE_RUNNING)return ESP_ERR_INVALID_STATE; ++ LIBSSH2_SESSION *ssh=ts_ssh_get_libssh2_session(shell->ssh_session); ++ int sock=ts_ssh_get_socket(shell->ssh_session); ++ int64_t deadline=esp_timer_get_time()+1000000; ++ size_t total=0; ++ while(totalchannel,data+total,len-total); ++ if(rc>0){total+=rc;if(written)*written=total;} ++ else if(rc==LIBSSH2_ERROR_EAGAIN && shell_wait(sock,ssh,deadline))continue; ++ else {shell->state=TS_SHELL_STATE_ERROR;return rc==LIBSSH2_ERROR_EAGAIN?ESP_ERR_TIMEOUT:ESP_FAIL;} ++ if(total=deadline){shell->state=TS_SHELL_STATE_ERROR;return ESP_ERR_TIMEOUT;} + } +- + return ESP_OK; + } + +-esp_err_t ts_ssh_shell_read(ts_ssh_shell_t shell, +- char *buffer, size_t buffer_size, +- size_t *read_len) ++esp_err_t ts_ssh_shell_read(ts_ssh_shell_t shell,char *buffer,size_t size,size_t *read_len) + { +- if (!shell || !buffer || buffer_size == 0) { +- return ESP_ERR_INVALID_ARG; +- } +- +- if (shell->state != TS_SHELL_STATE_RUNNING) { +- if (read_len) *read_len = 0; ++ if(read_len)*read_len=0; ++ if(!shell || !buffer || !size)return ESP_ERR_INVALID_ARG; ++ if(shell->state!=TS_SHELL_STATE_RUNNING)return ESP_ERR_INVALID_STATE; ++ int rc=libssh2_channel_read(shell->channel,buffer,size); ++ if(rc>0){if(read_len)*read_len=rc;return ESP_OK;} ++ if((rc==0 || rc==LIBSSH2_ERROR_EAGAIN) && libssh2_channel_eof(shell->channel)){ ++ shell->state=TS_SHELL_STATE_CLOSED; ++ shell->exit_code=libssh2_channel_get_exit_status(shell->channel); + return ESP_ERR_INVALID_STATE; + } +- +- int rc = libssh2_channel_read(shell->channel, buffer, buffer_size); +- +- if (rc > 0) { +- if (read_len) *read_len = rc; +- return ESP_OK; +- } else if (rc == 0) { +- /* EOF */ +- if (read_len) *read_len = 0; +- shell->state = TS_SHELL_STATE_CLOSED; +- shell->exit_code = libssh2_channel_get_exit_status(shell->channel); +- return ESP_ERR_INVALID_STATE; +- } else if (rc == LIBSSH2_ERROR_EAGAIN) { +- if (read_len) *read_len = 0; +- return ESP_ERR_TIMEOUT; +- } else { +- if (read_len) *read_len = 0; +- return ESP_FAIL; +- } ++ if(rc==0 || rc==LIBSSH2_ERROR_EAGAIN)return ESP_ERR_TIMEOUT; /* no data, not EOF */ ++ shell->state=TS_SHELL_STATE_ERROR; ++ return ESP_FAIL; + } + + esp_err_t ts_ssh_shell_set_output_cb(ts_ssh_shell_t shell, +@@ -359,124 +334,40 @@ esp_err_t ts_ssh_shell_set_close_cb(ts_ssh_shell_t shell, + + esp_err_t ts_ssh_shell_poll(ts_ssh_shell_t shell) + { +- if (!shell) { +- return ESP_ERR_INVALID_ARG; +- } +- +- if (shell->state != TS_SHELL_STATE_RUNNING) { +- return ESP_ERR_INVALID_STATE; +- } +- +- /* 检查通道是否关闭 */ +- if (libssh2_channel_eof(shell->channel)) { +- shell->state = TS_SHELL_STATE_CLOSED; +- shell->exit_code = libssh2_channel_get_exit_status(shell->channel); +- if (shell->close_cb) { +- shell->close_cb(shell->exit_code, shell->close_cb_data); +- } +- return ESP_ERR_INVALID_STATE; +- } +- +- /* 读取可用数据 */ +- int rc = libssh2_channel_read(shell->channel, shell->read_buffer, +- sizeof(shell->read_buffer)); +- +- if (rc > 0) { +- if (shell->output_cb) { +- shell->output_cb(shell->read_buffer, rc, shell->output_cb_data); +- } +- return ESP_OK; +- } else if (rc == LIBSSH2_ERROR_EAGAIN) { +- return ESP_ERR_TIMEOUT; +- } else if (rc == 0) { +- shell->state = TS_SHELL_STATE_CLOSED; +- shell->exit_code = libssh2_channel_get_exit_status(shell->channel); +- if (shell->close_cb) { +- shell->close_cb(shell->exit_code, shell->close_cb_data); +- } +- return ESP_ERR_INVALID_STATE; +- } else { +- return ESP_FAIL; +- } ++ if(!shell)return ESP_ERR_INVALID_ARG; ++ size_t n=0;esp_err_t ret=ts_ssh_shell_read(shell,shell->read_buffer,sizeof(shell->read_buffer),&n); ++ if(n && shell->output_cb)shell->output_cb(shell->read_buffer,n,shell->output_cb_data); ++ if(shell->state==TS_SHELL_STATE_CLOSED || shell->state==TS_SHELL_STATE_ERROR)shell_notify_close(shell); ++ return ret; + } + +-esp_err_t ts_ssh_shell_run(ts_ssh_shell_t shell, +- ts_shell_output_cb_t output_cb, +- ts_shell_input_cb_t input_cb, +- void *user_data) ++esp_err_t ts_ssh_shell_run(ts_ssh_shell_t shell,ts_shell_output_cb_t output_cb, ++ ts_shell_input_cb_t input_cb,void *data) + { +- if (!shell || !output_cb || !input_cb) { +- return ESP_ERR_INVALID_ARG; +- } +- +- if (shell->state != TS_SHELL_STATE_RUNNING) { +- return ESP_ERR_INVALID_STATE; +- } +- +- LIBSSH2_SESSION *ssh = ts_ssh_get_libssh2_session(shell->ssh_session); +- int sock = ts_ssh_get_socket(shell->ssh_session); +- +- while (shell->state == TS_SHELL_STATE_RUNNING) { +- bool activity = false; +- +- /* 检查本地输入(优先处理,提高响应性) */ +- size_t input_len = 0; +- const char *input = input_cb(&input_len, user_data); +- if (input && input_len > 0) { +- activity = true; +- size_t written = 0; +- while (written < input_len) { +- int rc = libssh2_channel_write(shell->channel, input + written, +- input_len - written); +- if (rc > 0) { +- written += rc; +- } else if (rc == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 10); +- } else { +- shell->state = TS_SHELL_STATE_ERROR; +- return ESP_FAIL; +- } +- } +- } +- +- /* 持续读取远程数据直到没有更多数据 */ +- int rc; ++ if(!shell || !output_cb || !input_cb)return ESP_ERR_INVALID_ARG; ++ if(shell->state!=TS_SHELL_STATE_RUNNING)return ESP_ERR_INVALID_STATE; ++ while(shell->state==TS_SHELL_STATE_RUNNING){ ++ size_t len=0;const char *input=input_cb(&len,data); ++ if(shell->state!=TS_SHELL_STATE_RUNNING)break; ++ if(input && len){esp_err_t ret=ts_ssh_shell_write(shell,input,len,NULL);if(ret!=ESP_OK)return ret;} ++ bool activity = len != 0; ++ size_t n; + do { +- rc = libssh2_channel_read(shell->channel, shell->read_buffer, +- sizeof(shell->read_buffer)); +- if (rc > 0) { +- activity = true; +- output_cb(shell->read_buffer, rc, user_data); +- } else if (rc == 0 || libssh2_channel_eof(shell->channel)) { +- /* 远程关闭 */ +- shell->exit_code = libssh2_channel_get_exit_status(shell->channel); +- shell->state = TS_SHELL_STATE_CLOSED; +- return ESP_OK; +- } +- } while (rc > 0); /* 继续读取直到 EAGAIN */ +- +- if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { +- /* 真正的错误 */ +- shell->state = TS_SHELL_STATE_ERROR; +- return ESP_FAIL; +- } +- +- /* 只在没有活动时短暂等待,避免 CPU 空转 */ +- if (!activity) { +- wait_socket(sock, ssh, 10); /* 减少等待时间到 10ms */ +- } +- } +- +- shell->exit_code = libssh2_channel_get_exit_status(shell->channel); +- shell->state = TS_SHELL_STATE_CLOSED; +- +- return ESP_OK; ++ n = 0; ++ esp_err_t ret = ts_ssh_shell_read(shell, shell->read_buffer, sizeof(shell->read_buffer), &n); ++ if (n) { output_cb(shell->read_buffer, n, data); activity = true; } ++ if (shell->state == TS_SHELL_STATE_CLOSED) return ESP_OK; ++ if (ret != ESP_OK && ret != ESP_ERR_TIMEOUT) return ret; ++ } while (n); /* preserve CLI's existing drain-until-no-data cadence */ ++ if(!activity)wait_socket(ts_ssh_get_socket(shell->ssh_session),ts_ssh_get_libssh2_session(shell->ssh_session),10); ++ } ++ return shell->state==TS_SHELL_STATE_CLOSED?ESP_OK:ESP_FAIL; + } + + esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t shell, + uint16_t width, uint16_t height) + { +- if (!shell) { ++ if (!shell || !width || !height) { + return ESP_ERR_INVALID_ARG; + } + +@@ -488,13 +379,15 @@ esp_err_t ts_ssh_shell_resize(ts_ssh_shell_t shell, + int sock = ts_ssh_get_socket(shell->ssh_session); + + int rc; ++ int64_t deadline=esp_timer_get_time()+1000000; + while ((rc = libssh2_channel_request_pty_size(shell->channel, width, height)) + == LIBSSH2_ERROR_EAGAIN) { +- wait_socket(sock, ssh, 100); ++ if(!shell_wait(sock,ssh,deadline)){shell->state=TS_SHELL_STATE_ERROR;return ESP_ERR_TIMEOUT;} + } + + if (rc != 0) { + ESP_LOGW(TAG, "Failed to resize PTY: %d", rc); ++ if(rc!=LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED)shell->state=TS_SHELL_STATE_ERROR; + return ESP_FAIL; + } + +diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c +index 5d0ca91..9bc83dc 100644 +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -179,11 +179,11 @@ static void power_policy_event_handler(const ts_event_t *event, void *user_data) + /* Request errors must go to the requester, never mutate an existing session. */ + static void ssh_request_error(httpd_req_t *req, const char *message) + { ++ TS_WS_TEST_POINT("request_error_encode"); + cJSON *msg=cJSON_CreateObject(); +- bool ok=msg && cJSON_AddStringToObject(msg,"type","ssh_status") && +- cJSON_AddStringToObject(msg,"status","error") && cJSON_AddStringToObject(msg,"message",message); ++ bool ok=msg && cJSON_AddStringToObject(msg,"type","error") && cJSON_AddStringToObject(msg,"message",message); + char *json=ok?cJSON_PrintUnformatted(msg):NULL;cJSON_Delete(msg); +- const char *text=json?json:"{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH request rejected\"}"; ++ const char *text=json?json:"{\"type\":\"error\",\"message\":\"SSH request rejected\"}"; + httpd_ws_frame_t frame={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)text,.len=strlen(text)}; + esp_err_t ret=httpd_ws_send_frame(req,&frame); + if(ret!=ESP_OK)TS_LOGW(TAG,"SSH request error could not be sent: %s",esp_err_to_name(ret)); +@@ -263,9 +263,10 @@ static void ssh_poll_task(void *arg) + xSemaphoreTake(ctx->io,portMAX_DELAY); + esp_err_t ret=ts_ssh_shell_read(ctx->shell,buf,sizeof(buf)-1,&n); + bool active=ts_ssh_shell_is_active(ctx->shell); ++ bool failed=ts_ssh_shell_get_state(ctx->shell)==TS_SHELL_STATE_ERROR; + xSemaphoreGive(ctx->io); + if(ret==ESP_OK && n)ssh_send_output(ctx,buf,n); +- if(!active){ssh_close(op,"closed","SSH session closed");break;} ++ if(!active){ssh_close(op,failed?"error":"closed",failed?"SSH channel failed; remote result is not confirmed":"SSH session closed");break;} + vTaskDelay(pdMS_TO_TICKS(20)); + } + shell_resources_close(ctx); +@@ -328,9 +329,10 @@ static void handle_ssh_control(httpd_req_t *req,ts_ws_peer_t peer,const char *ty + ssh_shell_context_t *ctx=ts_ws_op_data(op); + if(!strcmp(type,"ssh_disconnect"))ctx->disconnect_requested=true; + else { +- esp_err_t ret=ESP_ERR_INVALID_STATE; ++ esp_err_t ret=ESP_ERR_INVALID_ARG;bool active=false; + xSemaphoreTake(ctx->io,portMAX_DELAY); + if(ctx->shell && ts_ws_op_is_open(op)) { ++ active=true; + if(!strcmp(type,"ssh_input")) { + cJSON *data=cJSON_GetObjectItem(msg,"data"); + if(cJSON_IsString(data))ret=ts_ssh_shell_write(ctx->shell,data->valuestring,strlen(data->valuestring),NULL); +@@ -339,12 +341,18 @@ static void handle_ssh_control(httpd_req_t *req,ts_ws_peer_t peer,const char *ty + if(cJSON_IsString(signal))ret=ts_ssh_shell_send_signal(ctx->shell,signal->valuestring); + } else { + cJSON *w=cJSON_GetObjectItem(msg,"width"),*h=cJSON_GetObjectItem(msg,"height"); +- if(cJSON_IsNumber(w) && cJSON_IsNumber(h) && w->valueint>0 && h->valueint>0) ++ if(cJSON_IsNumber(w) && cJSON_IsNumber(h) && w->valuedouble>=1 && w->valuedouble<=UINT16_MAX && h->valuedouble>=1 && h->valuedouble<=UINT16_MAX && ++ w->valuedouble==w->valueint && h->valuedouble==h->valueint) + ret=ts_ssh_shell_resize(ctx->shell,w->valueint,h->valueint); + } + } ++ if(ctx->shell)active=ts_ssh_shell_is_active(ctx->shell); + xSemaphoreGive(ctx->io); +- if(ret!=ESP_OK)ssh_request_error(req,"SSH control could not be completed for this session"); ++ if(ret!=ESP_OK){ ++ if(!active)ssh_close(op,"error","SSH channel failed; remote result is not confirmed"); ++ else ssh_request_error(req,ret==ESP_ERR_NOT_SUPPORTED?"Unsupported SSH signal": ++ ret==ESP_ERR_INVALID_ARG?"Invalid SSH control parameters":"SSH control request failed; input was not replayed"); ++ } + } + ts_ws_op_release(op); + } +diff --git a/components/ts_webui/web/index.html b/components/ts_webui/web/index.html +index 25eb98c..d4aa9c9 100644 +--- a/components/ts_webui/web/index.html ++++ b/components/ts_webui/web/index.html +@@ -41,9 +41,9 @@ + .modal-content{background:var(--bg-card);border-radius:var(--radius-lg);max-width:600px;width:95%;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg)} + + +- +- +- ++ ++ ++ + + + +@@ -247,7 +247,7 @@ + + + +- +- +- +- +- ++ ++ ++ ++ ++ + + +diff --git a/components/ts_webui/web/js/lang/en-US.js b/components/ts_webui/web/js/lang/en-US.js +index 8eaf87b..cae057d 100644 +--- a/components/ts_webui/web/js/lang/en-US.js ++++ b/components/ts_webui/web/js/lang/en-US.js +@@ -3699,6 +3699,25 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('en-US', { + + // Terminal Page + terminal: { ++ sshCapacity: "The result channel is busy. SSH was not started; try again shortly.", ++ sshCreateFailed: "The SSH session could not be created. Try again shortly.", ++ sshOpenFailed: "The remote shell could not be opened. Check whether the server permits interactive sessions.", ++ sshStartupClosed: "The SSH session ended during startup. Check the server before reconnecting.", ++ sshStatusFailed: "SSH status notification failed. The connection state is unconfirmed; reconnect to check.", ++ sshOutputIncomplete: "SSH output in this page is incomplete. The remote result is unconfirmed. Check the server before repeating commands.", ++ sshClosed: "The SSH session has ended.", ++ sshClosing: "Closing the SSH session; waiting for confirmation.", ++ sshConnecting: "Establishing the SSH connection…", ++ sshReady: "The SSH shell is ready.", ++ sshServiceStopping: "The service is stopping. This request was not accepted.", ++ sshControlUnsupported: "Unsupported SSH signal; the session is still active.", ++ sshControlInvalid: "Invalid SSH control parameters; the session is still active.", ++ sshControlFailed: "This SSH request failed. Input was not replayed.", ++ sshChannelUnknown: "The SSH channel ended unexpectedly. The remote result is unconfirmed.", ++ sshWrongOwner: "This connection does not own an active SSH session.", ++ sshBusy: "Another SSH session is active. This connection attempt was rejected.", ++ sshRequestRejected: "This SSH request was rejected.", ++ + connecting: 'Connecting to device...', + connected: 'Connected to device', + helpHint: 'Enter {help} to view available commands', +diff --git a/components/ts_webui/web/js/lang/zh-CN.js b/components/ts_webui/web/js/lang/zh-CN.js +index cfebef2..1e2f124 100644 +--- a/components/ts_webui/web/js/lang/zh-CN.js ++++ b/components/ts_webui/web/js/lang/zh-CN.js +@@ -3663,6 +3663,25 @@ if (typeof i18n !== 'undefined') i18n.registerLanguage('zh-CN', { + + // 终端页面 + terminal: { ++ sshCapacity: "结果通知通道暂时繁忙,本次 SSH 连接未启动,请稍后重试。", ++ sshCreateFailed: "未能创建 SSH 会话,请稍后重试。", ++ sshOpenFailed: "未能启动远端交互式终端,请检查远端是否允许此类连接。", ++ sshStartupClosed: "SSH 会话在启动期间已结束,请检查远端状态后重新连接。", ++ sshStatusFailed: "SSH 状态通知未能完成,连接状态尚未确认,请重新连接。", ++ sshOutputIncomplete: "网页 SSH 输出不完整,远端执行结果尚未确认。请检查远端状态,不要直接重发命令。", ++ sshClosed: "SSH 会话已结束。", ++ sshClosing: "正在结束 SSH 会话,请等待确认。", ++ sshConnecting: "正在建立 SSH 连接…", ++ sshReady: "SSH 交互式终端已就绪。", ++ sshServiceStopping: "服务正在停止,本次请求未被接受。", ++ sshControlUnsupported: "不支持此 SSH 信号,会话仍可继续使用。", ++ sshControlInvalid: "SSH 控制参数无效,会话仍可继续使用。", ++ sshControlFailed: "本次 SSH 请求失败,输入未自动重发。", ++ sshChannelUnknown: "SSH 通道异常结束,远端执行结果尚未确认。", ++ sshWrongOwner: "此连接不属于当前有效的 SSH 会话。", ++ sshBusy: "已有 SSH 会话,本次连接请求未被接受。", ++ sshRequestRejected: "本次 SSH 请求未被接受。", ++ + connecting: '正在连接到设备...', + connected: '已连接到设备', + helpHint: '输入 {help} 查看可用命令', +diff --git a/components/ts_webui/web/js/terminal.js b/components/ts_webui/web/js/terminal.js +index 0f66d25..ccd3a51 100644 +--- a/components/ts_webui/web/js/terminal.js ++++ b/components/ts_webui/web/js/terminal.js +@@ -54,6 +54,7 @@ class WebTerminal { + // SSH Shell 模式 + this.sshMode = false; + this.sshConnecting = false; ++ this.sshDisconnecting = false; + this.restoring = false; + this.restoreTimer = null; + this.destroyed = false; +@@ -149,7 +150,7 @@ class WebTerminal { + */ + setupInputHandler() { + this.terminal.onData(data => { +- if (!this.connected) return; ++ if (!this.connected || this.sshConnecting || this.sshDisconnecting) return; + + // SSH Shell 模式 + if (this.sshMode) { +@@ -306,26 +307,31 @@ class WebTerminal { + */ + connect() { + if (this.destroyed) return; ++ if (this.ws) this.disconnect(); + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + const wsUrl = `${protocol}//${window.location.host}/ws`; + +- this.ws = new WebSocket(wsUrl); ++ const ws = new WebSocket(wsUrl); ++ this.ws = ws; ++ const current = () => !this.destroyed && this.ws === ws; + this.pingInterval = null; + +- this.ws.onopen = () => { ++ ws.onopen = () => { ++ if (!current()) return; + console.log('Terminal WebSocket connected'); + // 发送终端启动请求 +- this.ws.send(JSON.stringify({ type: 'terminal_start' })); ++ ws.send(JSON.stringify({ type: 'terminal_start' })); + + // 启动心跳机制 + this.pingInterval = setInterval(() => { +- if (this.ws && this.ws.readyState === WebSocket.OPEN) { +- this.ws.send(JSON.stringify({ type: 'ping' })); ++ if (current() && ws.readyState === WebSocket.OPEN) { ++ ws.send(JSON.stringify({ type: 'ping' })); + } + }, 15000); // 每15秒发送心跳 + }; + +- this.ws.onmessage = (event) => { ++ ws.onmessage = (event) => { ++ if (!current()) return; + try { + const msg = JSON.parse(event.data); + this.handleMessage(msg); +@@ -334,9 +340,11 @@ class WebTerminal { + } + }; + +- this.ws.onclose = (event) => { ++ ws.onclose = (event) => { ++ if (!current()) return; + console.log('Terminal WebSocket disconnected, code:', event.code); + this.connected = false; ++ this.sshMode = this.sshConnecting = this.sshDisconnecting = false; + if (this.restoring) this.finishRestore(false); + + // 清除心跳 +@@ -351,7 +359,7 @@ class WebTerminal { + if (event.code !== 1000) { // 非正常关闭 + this.writeln('\x1b[33m' + (typeof t === 'function' ? t('terminal.reconnectIn') : '5秒后尝试重新连接...') + '\x1b[0m'); + const tryReconnect = () => { +- if (this.destroyed || this.connected) return; ++ if (!current() || this.connected) return; + if (document.visibilityState !== 'visible') { + document.addEventListener('visibilitychange', function handler() { + document.removeEventListener('visibilitychange', handler); +@@ -366,7 +374,8 @@ class WebTerminal { + } + }; + +- this.ws.onerror = (error) => { ++ ws.onerror = (error) => { ++ if (!current()) return; + console.error('Terminal WebSocket error:', error); + this.writeln('\r\n\x1b[1;31m' + (typeof t === 'function' ? t('terminal.connectionError') : '连接错误') + '\x1b[0m'); + }; +@@ -384,8 +393,10 @@ class WebTerminal { + } + + handleMessage(msg) { ++ if (this.destroyed) return; + switch (msg.type) { + case 'connected': ++ if (this.sshMode || this.sshConnecting || this.sshDisconnecting) return; + if (this.restoring) this.finishRestore(true); + this.connected = true; + this.prompt = msg.prompt || 'tianshan> '; +@@ -403,18 +414,25 @@ class WebTerminal { + break; + + case 'done': ++ if (this.sshMode || this.sshConnecting || this.sshDisconnecting) return; + // 命令执行完成 + this.writePrompt(); + break; + + case 'error': { + const errMsg = msg.message || (typeof t === 'function' ? t('terminal.unknownError') : '未知错误'); ++ if (this.sshMode || this.sshConnecting || this.sshDisconnecting) { ++ this.writeln('\x1b[1;31m' + this.sshMessageText(errMsg) + '\x1b[0m'); ++ if (this.sshConnecting && !this.sshMode) { this.sshConnecting = false; this.writePrompt(); } ++ break; // request failure is not an operation terminal ++ } + if (errMsg.indexOf('Not a terminal session') >= 0 && this.ws && this.ws.readyState === WebSocket.OPEN) { + if (!this.restoring) { + this.restoring = true; this.connected = false; + this.ws.send(JSON.stringify({type: 'terminal_start'})); + showToast(t('promptRepair.terminalRestoring'), 'info'); +- this.restoreTimer = setTimeout(() => this.finishRestore(false, true), 10000); ++ const restoringSocket = this.ws; ++ this.restoreTimer = setTimeout(() => { if (!this.destroyed && this.ws === restoringSocket && this.restoring) this.finishRestore(false, true); }, 10000); + } + } else { + if (this.restoring) this.finishRestore(false); +@@ -446,6 +464,7 @@ class WebTerminal { + + case 'session_closed': + this.connected = false; ++ this.sshMode = this.sshConnecting = this.sshDisconnecting = false; + this.writeln('\x1b[33m' + (typeof t === 'function' ? t('terminal.sessionClosed') : '会话已关闭,请重新连接') + '\x1b[0m'); + break; + +@@ -593,10 +612,9 @@ class WebTerminal { + startSshShell(params) { + if (this.sshConnecting || this.sshMode) { + this.writeln('\x1b[1;31m' + (typeof t === 'function' ? t('terminal.sshSessionInProgress') : 'SSH 会话已在进行中') + '\x1b[0m'); +- this.writePrompt(); + return; + } +- ++ if (!this.connected || !this.ws || this.ws.readyState !== WebSocket.OPEN) return; + this.sshConnecting = true; + const connMsg = typeof t === 'function' ? t('terminal.sshConnectingTo', { user: params.user, host: params.host, port: params.port }) : `正在连接到 ${params.user}@${params.host}:${params.port}...`; + this.writeln(`\x1b[36m${connMsg}\x1b[0m`); +@@ -627,29 +645,66 @@ class WebTerminal { + /** + * 处理 SSH 状态消息 + */ ++ sshMessageText(message) { ++ const keys = { ++ "Missing host or user": "sshShellRequiresParams", ++ "SSH result delivery capacity unavailable": "sshCapacity", ++ "Failed to create SSH session": "sshCreateFailed", ++ "Failed to open shell": "sshOpenFailed", ++ "SSH shell closed during startup": "sshStartupClosed", ++ "SSH connection status delivery failed": "sshStatusFailed", ++ "SSH readiness delivery failed": "sshStatusFailed", ++ "SSH status delivery failed": "sshStatusFailed", ++ "SSH output delivery incomplete; remote command result is not confirmed": "sshOutputIncomplete", ++ "SSH session closed": "sshClosed", ++ "Closing SSH session...": "sshClosing", ++ "Connecting to SSH server...": "sshConnecting", ++ "SSH shell ready": "sshReady", ++ "Service is stopping": "sshServiceStopping", ++ 'Unsupported SSH signal': 'sshControlUnsupported', ++ 'Invalid SSH control parameters': 'sshControlInvalid', ++ 'SSH control request failed; input was not replayed': 'sshControlFailed', ++ 'SSH channel failed; remote result is not confirmed': 'sshChannelUnknown', ++ 'This connection does not own an active SSH session': 'sshWrongOwner', ++ 'Another SSH session is active': 'sshBusy', ++ 'SSH request rejected': 'sshRequestRejected' ++ }; ++ return keys[message] && typeof t === 'function' ? t('terminal.' + keys[message]) : message; ++ } ++ + handleSshStatus(msg) { + const status = msg.status; +- const message = msg.message || ''; ++ const message = this.sshMessageText(msg.message || ''); + + switch (status) { + case 'connecting': + this.writeln(`\x1b[33m${message}\x1b[0m`); + break; + case 'connected': ++ if (!this.sshConnecting) return; ++ this.sshDisconnecting = false; + this.sshMode = true; + this.sshConnecting = false; + this.writeln(`\x1b[1;32m${message}\x1b[0m`); + this.writeln('\x1b[90m' + (typeof t === 'function' ? t('terminal.exitSshHint') : '(按 Ctrl+\\ 退出 SSH shell)') + '\x1b[0m'); + this.writeln(''); + break; +- case 'closed': + case 'disconnecting': ++ if (!this.sshMode) return; ++ this.sshDisconnecting = true; ++ this.writeln(`\r\n\x1b[33m${message}\x1b[0m`); ++ break; ++ case 'closed': ++ if (!this.sshMode && !this.sshConnecting) return; ++ this.sshDisconnecting = false; + this.sshMode = false; + this.sshConnecting = false; + this.writeln(`\r\n\x1b[33m${message}\x1b[0m`); + this.writePrompt(); + break; + case 'error': ++ if (!this.sshMode && !this.sshConnecting) return; ++ this.sshDisconnecting = false; + this.sshMode = false; + this.sshConnecting = false; + this.writeln(`\x1b[1;31m${message}\x1b[0m`); +@@ -725,6 +780,7 @@ class WebTerminal { + this.ws = null; + } + this.connected = false; ++ this.sshMode = this.sshConnecting = this.sshDisconnecting = false; + } + + /** +diff --git a/tests/ws_subscriptions/test_operation_adapter.c b/tests/ws_subscriptions/test_operation_adapter.c +index fa881f7..4a98321 100644 +--- a/tests/ws_subscriptions/test_operation_adapter.c ++++ b/tests/ws_subscriptions/test_operation_adapter.c +@@ -68,11 +68,15 @@ static int adapter_create_caps(void(*fn)(void*),const char *n,unsigned stack,voi + #undef heap_caps_calloc + #undef xTaskCreate + #undef xTaskCreateWithCaps ++#ifndef PROJECT_REAL_DRIVER + struct ts_ssh_session_s {bool aborted;ts_ssh_config_t config;}; ++#endif + static unsigned control_writes,control_signals,control_resizes,commands_submitted; + static void (*stage_hook)(const char *); + static void stage(const char *name){if(stage_hook)stage_hook(name);} ++#ifndef PROJECT_REAL_DRIVER + struct ts_ssh_shell_s {bool active;}; ++#endif + static unsigned aborts,variable_writes,session_destroys; + static int remote_failure; + static void (*remote_hook)(void); +@@ -92,6 +96,7 @@ BaseType_t xTimerPendFunctionCall(void(*fn)(void*,uint32_t),void *arg,uint32_t v + assert(timer_queued<16);timer_queue[timer_queued++]=(typeof(timer_queue[0])){fn,arg,v,NULL};return pdPASS; + } + static void timer_pump(void){while(timer_queued){typeof(timer_queue[0]) q=timer_queue[0];memmove(timer_queue,timer_queue+1,--timer_queued*sizeof(*timer_queue));if(q.deleted){free(q.deleted);host_timer=NULL;}else q.fn(q.arg,q.value);}} ++#ifndef PROJECT_REAL_DRIVER + esp_err_t ts_ssh_session_create(const ts_ssh_config_t*c,ts_ssh_session_t *out){stage("create");if(remote_failure==1)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));if(*out)(*out)->config=*c;return *out?ESP_OK:ESP_ERR_NO_MEM;} + esp_err_t ts_ssh_connect(ts_ssh_session_t s){stage("connect");if(s->config.cancelled && s->config.cancelled(s->config.cancel_context))return ESP_ERR_TIMEOUT;stage("auth");return remote_failure==2?ESP_FAIL:ESP_OK;} + const char *ts_ssh_get_error(ts_ssh_session_t s){(void)s;return "fake network error";} +@@ -100,6 +105,7 @@ esp_err_t ts_ssh_session_destroy(ts_ssh_session_t s){session_destroys++;tracked_ + void ts_ssh_abort(ts_ssh_session_t s){s->aborted=true;aborts++;} + esp_err_t ts_ssh_shell_open(ts_ssh_session_t s,const ts_shell_config_t*c,ts_ssh_shell_t *out){(void)s;(void)c;if(remote_failure==3)return ESP_FAIL;*out=host_calloc(1,sizeof(**out));(*out)->active=true;return 0;} + bool ts_ssh_shell_is_active(ts_ssh_shell_t s){return s&&s->active;} ++ts_shell_state_t ts_ssh_shell_get_state(ts_ssh_shell_t s){return s&&s->active?TS_SHELL_STATE_RUNNING:TS_SHELL_STATE_CLOSED;} + esp_err_t ts_ssh_shell_close(ts_ssh_shell_t s){tracked_free(s);return 0;} + esp_err_t ts_ssh_shell_read(ts_ssh_shell_t s,char *b,size_t n,size_t *out){(void)b;(void)n;*out=0;s->active=false;return 0;} + esp_err_t ts_ssh_shell_write(ts_ssh_shell_t s,const char *b,size_t n,size_t *out){(void)s;(void)b;(void)n;(void)out;control_writes++;return 0;} +@@ -109,6 +115,9 @@ esp_err_t ts_ssh_exec_stream(ts_ssh_session_t s,const char *command,ts_ssh_outpu + (void)command;stage("submit");if(s->config.cancelled && s->config.cancelled(s->config.cancel_context))return ESP_ERR_TIMEOUT;commands_submitted++;if(remote_hook)remote_hook();if(remote_timeout && host_timer)host_timer->fn(host_timer); + cb("value=42\n",9,false,arg);*code=0;return s->aborted || (s->config.cancelled && s->config.cancelled(s->config.cancel_context))?ESP_ERR_TIMEOUT:ESP_OK; + } ++#else ++#include "project_driver.inc" ++#endif + esp_err_t ts_keystore_load_private_key(const char *id,char **out,size_t *n){(void)id;stage("key");*out=host_strdup("fake-key");*n=9;return ESP_OK;} + esp_err_t ts_variable_upsert(const ts_auto_variable_t *v){(void)v;variable_writes++;return 0;} + esp_err_t ts_console_exec(const char *cmd,ts_cmd_result_t *result){(void)cmd;memset(result,0,sizeof(*result));return 0;} +@@ -121,7 +130,11 @@ esp_err_t ts_log_remove_callback(ts_log_callback_handle_t h){(void)h;return remo + size_t ts_log_buffer_search(ts_log_entry_t *e,size_t n,ts_log_level_t min,ts_log_level_t max,const char *tag,const char *keyword){(void)e;(void)n;(void)min;(void)max;(void)tag;(void)keyword;return 0;} + httpd_handle_t ts_http_server_get_handle(void){return (void*)11;} + void ts_http_server_set_stop_hooks(esp_err_t(*stop)(httpd_handle_t),void(*stopped)(httpd_handle_t)){(void)stop;(void)stopped;} +-static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){(void)caps;if(close_during_create)((ssh_shell_context_t*)arg)->shell->active=false;return adapter_create(fn,n,stack,arg,p,out);} ++static int adapter_create_caps(void(*fn)(void*),const char*n,unsigned stack,void*arg,unsigned p,TaskHandle_t*out,unsigned caps){(void)caps; ++#ifndef PROJECT_REAL_DRIVER ++if(close_during_create)((ssh_shell_context_t*)arg)->shell->active=false; ++#endif ++return adapter_create(fn,n,stack,arg,p,out);} + static void drive_all(void){for(unsigned i=0;i<12;i++){ts_ws_op_poll();pump();timer_pump();}assert(!timer_queued);} + static void setup(void){start();memset(s_clients,0,sizeof(s_clients));s_server=(void*)11;s_ws_stopping=false;ts_ws_op_enable();transport_server.closed=peer_closed;for(int fd=1;fd<=2;fd++){reqs[fd]=(httpd_req_t){.handle=(void*)11,.fd=fd};current=(void*)3;assert(add_client(&reqs[fd],WS_CLIENT_TYPE_EVENT)==ESP_OK);}current=(void*)1;} + static void finish_all(void){drive_all();assert(!ts_ws_op_busy());stop();assert(!live_allocations);} +diff --git a/tests/ws_subscriptions/measure_project_v3.py b/tests/ws_subscriptions/measure_project_v3.py +new file mode 100644 +index 0000000..139b558 +--- /dev/null ++++ b/tests/ws_subscriptions/measure_project_v3.py +@@ -0,0 +1,23 @@ ++#!/usr/bin/env python3 ++"""Use the actual fixed-SDK compile commands; no target execution.""" ++import os,json,pathlib,shlex,subprocess,tarfile,tempfile ++root=pathlib.Path(__file__).resolve().parents[2];build=pathlib.Path(os.environ.get('V3_BUILD','/tmp/tianshan-project-v3-build/build'));doc=root/'docs/repair/ws-project-v3' ++commands=json.loads((build/'compile_commands.json').read_text());result={} ++with tempfile.TemporaryDirectory(prefix='ts-v3-size-') as d: ++ temp=pathlib.Path(d) ++ for rel,typ in [('components/ts_security/src/ts_ssh_shell.c','struct ts_ssh_shell_s'),('components/ts_webui/src/ts_webui_ws.c','ssh_shell_context_t')]: ++ entry=next(c for c in commands if c['file']==str(root/rel));base=shlex.split(entry['command']);result[rel]={} ++ for kind in ['before','after']: ++ if kind=='before': ++ with tarfile.open(doc/'baseline.tar.gz') as t:source=t.extractfile(rel).read().decode() ++ else:source=(root/rel).read_text() ++ src=temp/(kind+'-'+pathlib.Path(rel).name);src.write_text(source+'\nconst unsigned char v3_object_size[sizeof('+typ+')]={0};\n') ++ obj=src.with_suffix('.o');args=base[:];args[args.index('-o')+1]=str(obj);args[args.index('-c')+1]=str(src);args+=['-fstack-usage'] ++ subprocess.run(args,cwd=entry['directory'],check=True,capture_output=True) ++ nm=str(pathlib.Path(args[0]).with_name('xtensa-esp32s3-elf-nm'));nm=nm if pathlib.Path(nm).exists() else str(pathlib.Path(args[0]).with_name('xtensa-esp-elf-nm')) ++ symbols=subprocess.check_output([nm,'-S',str(obj)],text=True) ++ size=int(next(l.split()[1] for l in symbols.splitlines() if l.endswith(' v3_object_size')),16) ++ stack={l.split('\t')[0].rsplit(':',1)[-1]:l.split('\t')[1:] for l in src.with_suffix('.su').read_text().splitlines()} ++ result[rel][kind]={'object_bytes':size,'stack_usage':stack} ++(doc/'target-resource.json').write_text(json.dumps(result,indent=2)) ++print(json.dumps({k:{x:v[x]['object_bytes'] for x in v} for k,v in result.items()},indent=2)) +diff --git a/tests/ws_subscriptions/project_driver.inc b/tests/ws_subscriptions/project_driver.inc +new file mode 100644 +index 0000000..efe9497 +--- /dev/null ++++ b/tests/ws_subscriptions/project_driver.inc +@@ -0,0 +1,69 @@ ++/* Real project SSH client + Shell; only libssh2/socket/clock boundaries fake. */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ts_known_hosts.h" ++struct _LIBSSH2_SESSION {bool local_closed;}; ++struct _LIBSSH2_CHANNEL {LIBSSH2_SESSION *owner;}; ++static LIBSSH2_CHANNEL *driver_channel; ++static int driver_channels,driver_sessions,driver_sockets,driver_writes,driver_phase,driver_reads; ++static bool driver_eof,driver_write_fail,driver_write_again,driver_resize_reject,driver_close_again,driver_partial,driver_read_fail; ++static int driver_socket(int d,int t,int p){(void)d;(void)t;(void)p;driver_sockets++;return 10;} ++static int driver_close(int fd){(void)fd;driver_sockets--;return 0;} ++static int driver_connect(int fd,const struct sockaddr*a,socklen_t n){(void)fd;(void)a;(void)n;return 0;} ++static int driver_fcntl(int fd,int cmd,...){(void)fd;(void)cmd;return 0;} ++static int driver_select(int n,fd_set*r,fd_set*w,fd_set*x,struct timeval*t){(void)n;(void)r;(void)w;(void)x;test_now+=(int64_t)t->tv_sec*1000000+t->tv_usec;return 0;} ++int libssh2_init(int f){(void)f;return 0;} ++void libssh2_exit(void){} ++LIBSSH2_SESSION *libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*a)),LIBSSH2_FREE_FUNC((*f)),LIBSSH2_REALLOC_FUNC((*r)),void*x){(void)a;(void)f;(void)r;(void)x;driver_sessions++;return calloc(1,sizeof(LIBSSH2_SESSION));} ++int libssh2_channel_free(LIBSSH2_CHANNEL*c){if(driver_close_again && !c->owner->local_closed)return LIBSSH2_ERROR_EAGAIN;assert(c==driver_channel);driver_channel=NULL;driver_channels--;free(c);return 0;} ++int libssh2_session_free(LIBSSH2_SESSION*s){if(driver_channel){int r=libssh2_channel_free(driver_channel);if(r)return r;}driver_sessions--;free(s);return 0;} ++void libssh2_session_set_blocking(LIBSSH2_SESSION*s,int b){(void)s;assert(!b);} ++void *libssh2_session_callback_set(LIBSSH2_SESSION*s,int c,void*f){(void)c;(void)f;s->local_closed=true;return NULL;} ++int libssh2_session_handshake(LIBSSH2_SESSION*s,libssh2_socket_t f){(void)s;(void)f;return 0;} ++int libssh2_session_block_directions(LIBSSH2_SESSION*s){(void)s;return LIBSSH2_SESSION_BLOCK_INBOUND;} ++int libssh2_session_last_errno(LIBSSH2_SESSION*s){(void)s;return driver_phase==1?LIBSSH2_ERROR_EAGAIN:0;} ++int libssh2_session_last_error(LIBSSH2_SESSION*s,char **m,int*n,int w){(void)s;(void)n;(void)w;*m="boundary rejection";return 0;} ++int libssh2_userauth_password_ex(LIBSSH2_SESSION*s,const char*u,unsigned int l,const char*p,unsigned int n,LIBSSH2_PASSWD_CHANGEREQ_FUNC((*change))){(void)s;(void)u;(void)l;(void)p;(void)n;(void)change;return 0;} ++int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION*s,const char*u,unsigned int l,const char*a,const char*b,const char*p){(void)a;(void)b;return libssh2_userauth_password_ex(s,u,l,p,0,NULL);} ++int libssh2_userauth_publickey_frommemory(LIBSSH2_SESSION*s,const char*u,size_t l,const char*a,size_t al,const char*b,size_t bl,const char*p){(void)a;(void)al;(void)b;(void)bl;return libssh2_userauth_password_ex(s,u,l,p,0,NULL);} ++LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION*s,const char*t,unsigned int l,unsigned int w,unsigned int p,const char*m,unsigned int ml){(void)t;(void)l;(void)w;(void)p;(void)m;(void)ml;if(driver_phase==1)return NULL;assert(!driver_channel);driver_channel=calloc(1,sizeof(*driver_channel));driver_channel->owner=s;driver_channels++;return driver_channel;} ++int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL*c,const char*t,unsigned int l,const char*m,unsigned int ml,int w,int h,int wp,int hp){(void)c;(void)t;(void)l;(void)m;(void)ml;(void)w;(void)h;(void)wp;(void)hp;return driver_phase==2?LIBSSH2_ERROR_EAGAIN:driver_phase==4?-1:0;} ++int libssh2_channel_process_startup(LIBSSH2_CHANNEL*c,const char*r,unsigned int rl,const char*m,unsigned int ml){(void)c;(void)r;(void)rl;(void)m;(void)ml;return driver_phase==3?LIBSSH2_ERROR_EAGAIN:0;} ++int libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL*c,int w,int h,int wp,int hp){(void)c;(void)w;(void)h;(void)wp;(void)hp;return driver_resize_reject?LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED:0;} ++ssize_t libssh2_channel_write_ex(LIBSSH2_CHANNEL*c,int stream,const char*b,size_t n){(void)c;(void)stream;(void)b;if(driver_partial){driver_partial=false;driver_write_fail=true;driver_writes++;return 1;}if(driver_write_again)return LIBSSH2_ERROR_EAGAIN;if(driver_write_fail)return LIBSSH2_ERROR_SOCKET_SEND;driver_writes++;return n;} ++ssize_t libssh2_channel_read_ex(LIBSSH2_CHANNEL*c,int stream,char*b,size_t n){(void)c;(void)stream;(void)b;(void)n;driver_reads++;return driver_read_fail?LIBSSH2_ERROR_SOCKET_RECV:0;} ++int libssh2_channel_eof(LIBSSH2_CHANNEL*c){(void)c;return driver_eof;} ++int libssh2_channel_send_eof(LIBSSH2_CHANNEL*c){(void)c;return driver_close_again?LIBSSH2_ERROR_EAGAIN:0;} ++int libssh2_channel_wait_eof(LIBSSH2_CHANNEL*c){(void)c;return driver_close_again?LIBSSH2_ERROR_EAGAIN:0;} ++int libssh2_channel_close(LIBSSH2_CHANNEL*c){return driver_close_again&&!c->owner->local_closed?LIBSSH2_ERROR_EAGAIN:0;} ++int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL*c){(void)c;return 0;} ++esp_err_t ts_known_hosts_verify(ts_ssh_session_t s,ts_host_verify_result_t*r,ts_known_host_t*h){(void)s;(void)h;*r=TS_HOST_VERIFY_OK;return ESP_OK;} ++#define socket driver_socket ++#define close driver_close ++#define connect driver_connect ++#define fcntl driver_fcntl ++#define select driver_select ++#define malloc tracked_malloc ++#define calloc host_calloc ++#define free tracked_free ++#define TAG client_tag ++#define wait_socket client_wait_socket ++#include "../../components/ts_security/src/ts_ssh_client.c" ++#undef wait_socket ++#undef TAG ++#define TAG shell_tag ++#include "../../components/ts_security/src/ts_ssh_shell.c" ++#undef TAG ++#undef malloc ++#undef calloc ++#undef free ++#undef socket ++#undef close ++#undef connect ++#undef fcntl ++#undef select +diff --git a/tests/ws_subscriptions/project_stubs/ts_core.h b/tests/ws_subscriptions/project_stubs/ts_core.h +new file mode 100644 +index 0000000..b3a531d +--- /dev/null ++++ b/tests/ws_subscriptions/project_stubs/ts_core.h +@@ -0,0 +1,4 @@ ++#pragma once ++#define TS_MALLOC_PSRAM(n) tracked_malloc(n) ++#define TS_CALLOC_PSRAM(n,z) host_calloc(n,z) ++#define TS_REALLOC_PSRAM(p,n) realloc(p,n) +diff --git a/tests/ws_subscriptions/replay_project_baseline.py b/tests/ws_subscriptions/replay_project_baseline.py +new file mode 100644 +index 0000000..f1e73b4 +--- /dev/null ++++ b/tests/ws_subscriptions/replay_project_baseline.py +@@ -0,0 +1,31 @@ ++#!/usr/bin/env python3 ++"""Replay frozen pre-v3 product source; no checkout or mutation of working source.""" ++import hashlib,json,os,pathlib,shutil,subprocess,tarfile,tempfile ++root=pathlib.Path(__file__).resolve().parents[2];doc=root/'docs/repair/ws-project-v3' ++with tempfile.TemporaryDirectory(prefix='ts-v3-baseline-') as name: ++ dst=pathlib.Path(name) ++ with tarfile.open(doc/'baseline.tar.gz') as t:t.extractall(dst,filter='data') ++ for file,digest in json.loads((doc/'baseline.json').read_text())['sha256'].items(): ++ assert hashlib.sha256((dst/file).read_bytes()).hexdigest()==digest,file ++ (dst/'components/ts_console/commands').mkdir(parents=True,exist_ok=True) ++ shutil.copy2(doc/'baseline-console.c',dst/'components/ts_console/commands/ts_cmd_ssh.c') ++ # Console header only; do not replace the frozen callback with today's code. ++ (dst/'components/ts_console/include').symlink_to(root/'components/ts_console/include',target_is_directory=True) ++ # Dependencies outside the frozen affected units are read-only current headers/vendor. ++ for p in (root/'components').iterdir(): ++ if not (dst/'components'/p.name).exists():(dst/'components'/p.name).symlink_to(p,target_is_directory=p.is_dir()) ++ with tarfile.open(doc/'baseline-fixture.tar.gz') as t:t.extractall(dst,filter='data') ++ p=subprocess.run(['node','tests/prompts/project-cross.cjs','--baseline'],cwd=dst,env=dict(os.environ,CROSS_OUTPUT=str(doc/'baseline-h1.json')),capture_output=True,text=True) ++ (doc/'baseline-h1.txt').write_text(p.stdout+p.stderr);assert p.returncode==0 and 'CONFIRMED H1' in p.stdout,p.stdout+p.stderr ++ # Same current lower-driver assertions against the frozen production, separate from H1. ++ for file in ['test_shell_driver.c','run_shell_driver.sh','project_driver.inc']: ++ shutil.copy2(root/'tests/ws_subscriptions'/file,dst/'tests/ws_subscriptions'/file) ++ for args,label,marker in [([], 'no-data','ESP_ERR_TIMEOUT'),(['--eof-only'],'eof-release','!live_allocations'),(['--cli-exit'],'cli-exit','!ts_ssh_shell_is_active(shell)')]: ++ p=subprocess.run(['bash','tests/ws_subscriptions/run_shell_driver.sh',*args],cwd=dst,env=dict(os.environ,PROJECT_BASELINE='1'),capture_output=True,text=True) ++ evidence=p.stdout+p.stderr;(doc/('baseline-'+label+'.txt')).write_text(evidence) ++ assert p.returncode!=0 and 'Assertion failed:' in evidence and marker in evidence,evidence ++ print('CONFIRMED production defect:',label) ++ p=subprocess.run(['bash','tests/ws_subscriptions/run_shell_driver.sh','--metrics'],cwd=dst,env=dict(os.environ,PROJECT_BASELINE='1'),capture_output=True,text=True) ++ assert p.returncode==0,p.stderr ++ (doc/'baseline-allocation-metrics.json').write_text(p.stdout) ++ print('CONFIRMED H1 and lower-driver business counterexamples; source hashes verified') +diff --git a/tests/ws_subscriptions/run_project_bridge.sh b/tests/ws_subscriptions/run_project_bridge.sh +new file mode 100644 +index 0000000..9609ec6 +--- /dev/null ++++ b/tests/ws_subscriptions/run_project_bridge.sh +@@ -0,0 +1,11 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++: "${IDF_PATH:?NOT RUN: set IDF_PATH to the project SDK}" ++build=$(mktemp -d /tmp/ts-ws-adapter.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++cjson="$IDF_PATH/components/json/cJSON" ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -Wno-macro-redefined -fsanitize=address,undefined \ ++ -Itests/ws_subscriptions/project_stubs -Icomponents/ch405labs_esp_libssh2/libssh2/include -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -Icomponents/ts_security/include -Icomponents/ts_automation/include -Icomponents/ts_drivers/include -Icomponents/ts_console/include -Icomponents/ts_net/include -I"$cjson" \ ++ tests/ws_subscriptions/test_project.c "$cjson/cJSON.c" -o "$build/adapter" ++"$build/adapter" +diff --git a/tests/ws_subscriptions/run_project_v3.py b/tests/ws_subscriptions/run_project_v3.py +new file mode 100644 +index 0000000..5fb597c +--- /dev/null ++++ b/tests/ws_subscriptions/run_project_v3.py +@@ -0,0 +1,19 @@ ++#!/usr/bin/env python3 ++"""Local suite entry; no device access. Preserve every subprocess exit status.""" ++import json, os, pathlib, subprocess, sys ++root=pathlib.Path(__file__).resolve().parents[2] ++out=pathlib.Path(os.environ.get('V3_RESULTS',str(root/'docs/repair/ws-project-v3/results')));out.mkdir(parents=True,exist_ok=True) ++commands=[('host',['bash','tests/ws_subscriptions/run_host.sh']),('operation',['bash','tests/ws_subscriptions/run_operation.sh']),('adapter',['bash','tests/ws_subscriptions/run_operation_adapter.sh']),('control',['bash','tests/ws_subscriptions/run_control.sh']),('reviewer',['bash','tests/ws_subscriptions/run_reviewer.sh']),('f1_f2',['bash','tests/ws_subscriptions/run_f1_f2.sh']),('runtime',['bash','tests/runtime/run_all.sh']),('certificate',['bash','tests/certificate/run_host.sh']),('prompts',['npm','test','--prefix','tests/prompts']),('release',['python3','tests/release/test_release.py']),('shell_driver',['bash','tests/ws_subscriptions/run_shell_driver.sh'])] ++if '--browser' in sys.argv: commands=[('browser',['npm','run','test:browser','--prefix','tests/prompts'])] ++results=[] ++for name,cmd in commands: ++ with (out/(name+'.log')).open('w') as f:r=subprocess.run(cmd,cwd=root,stdout=f,stderr=subprocess.STDOUT) ++ results.append(dict(name=name,command=cmd,exit=r.returncode));print(name,r.returncode,flush=True) ++for language in ['en-US','zh-CN']: ++ name=('cross-browser-' if '--browser' in sys.argv else 'cross-node-')+language ++ env=dict(os.environ,CROSS_LANGUAGE=language,CROSS_OUTPUT=str(out/(name+'.json'))) ++ cmd=['node','tests/prompts/project-cross.cjs']+(['--browser'] if '--browser' in sys.argv else []) ++ with (out/(name+'.log')).open('w') as f:r=subprocess.run(cmd,cwd=root,env=env,stdout=f,stderr=subprocess.STDOUT) ++ results.append(dict(name=name,command=cmd,exit=r.returncode));print(name,r.returncode,flush=True) ++(out/('browser.json' if '--browser' in sys.argv else 'host.json')).write_text(json.dumps(results,indent=2)) ++sys.exit(any(r['exit'] for r in results)) +diff --git a/tests/ws_subscriptions/run_shell_driver.sh b/tests/ws_subscriptions/run_shell_driver.sh +new file mode 100644 +index 0000000..fb52e4f +--- /dev/null ++++ b/tests/ws_subscriptions/run_shell_driver.sh +@@ -0,0 +1,19 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++: "${IDF_PATH:?NOT RUN: set IDF_PATH to the project SDK}" ++build=$(mktemp -d /tmp/ts-ws-adapter.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++cjson="$IDF_PATH/components/json/cJSON" ++extra=() ++if [[ "${PROJECT_BASELINE:-0}" == 1 ]]; then extra+=(-DPROJECT_BASELINE); fi ++python3 - "$build" <<'PYCLI' ++import pathlib,sys ++s=pathlib.Path('components/ts_console/commands/ts_cmd_ssh.c').read_text() ++a=s.index('static const char *shell_input_callback(');b=s.index('static int do_ssh_shell(',a) ++pathlib.Path(sys.argv[1],'cli_shell_fixture.inc').write_text(s[a:b]) ++PYCLI ++"${CC:-cc}" -std=gnu11 -g -Wno-deprecated-declarations -Wno-macro-redefined -fsanitize=address,undefined \ ++ "${extra[@]}" -I"$build" -Itests/ws_subscriptions/project_stubs -Icomponents/ch405labs_esp_libssh2/libssh2/include -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -Icomponents/ts_security/include -Icomponents/ts_automation/include -Icomponents/ts_drivers/include -Icomponents/ts_console/include -Icomponents/ts_net/include -I"$cjson" \ ++ tests/ws_subscriptions/test_shell_driver.c "$cjson/cJSON.c" -o "$build/adapter" ++"$build/adapter" "$@" +diff --git a/tests/ws_subscriptions/test_project.c b/tests/ws_subscriptions/test_project.c +new file mode 100644 +index 0000000..b7b63f7 +--- /dev/null ++++ b/tests/ws_subscriptions/test_project.c +@@ -0,0 +1,40 @@ ++#define OP_ADAPTER_NO_MAIN ++#define PROJECT_REAL_DRIVER ++#include "test_operation_adapter.c" ++static void emit(httpd_ws_frame_t*f){ ++ printf("{\"frame\":%.*s,\"fd\":%d,\"bytes\":\"",(int)f->len,f->payload,sent_fd); ++ for(size_t i=0;ilen;i++){unsigned char c=f->payload[i];if(c=='"'||c=='\\')putchar('\\');if(c<32)printf("\\u%04x",c);else putchar(c);}puts("\"}"); ++} ++static void close_during_error(void){ssh_shell_context_t *ctx=shell_task.arg;ssh_send_output(ctx,"last output",11);ssh_close(ctx->op,"closed","SSH session closed");} ++static void fail_error_encoding(void){fail_allocation=allocations+1;} ++int main(void){ ++ cJSON_Hooks h={tracked_malloc,tracked_free};cJSON_InitHooks(&h);sent_hook=emit;setup(); ++ char line[4096];while(fgets(line,sizeof(line),stdin)){ ++ cJSON *j=cJSON_Parse(line);assert(j);const char *cmd=cJSON_GetStringValue(cJSON_GetObjectItem(j,"cmd")); ++ if(cmd && !strcmp(cmd,"finish")){ssh_cleanup();if(shell_task.fn){shell_task.fn(shell_task.arg);shell_task.fn=NULL;}drive_all();cJSON_Delete(j);finish_all();assert(!driver_channels&&!driver_sessions&&!driver_sockets);puts("{\"finished\":true}");return 0;} ++ if(cmd && !strcmp(cmd,"eof")){driver_eof=true;shell_task.fn(shell_task.arg);shell_task.fn=NULL;drive_all();} ++ else if(cmd && !strcmp(cmd,"output")){ssh_shell_context_t *ctx=shell_task.arg;ssh_send_output(ctx,"stream",6);} ++ else if(cmd && !strcmp(cmd,"error_close")){barrier_name="request_error_encode";barrier_action=close_during_error;} ++ else if(cmd && !strcmp(cmd,"write_again"))driver_write_again=true; ++ else if(cmd && !strcmp(cmd,"close_again"))driver_close_again=true; ++ else if(cmd && !strcmp(cmd,"reset_driver")){driver_write_fail=driver_write_again=driver_resize_reject=driver_close_again=driver_eof=false;driver_phase=0;} ++ else if(cmd && !strcmp(cmd,"setup_fail"))driver_phase=4; ++ else if(cmd && !strcmp(cmd,"queue_fail"))queue_fail=true; ++ else if(cmd && !strcmp(cmd,"queue_resume")){queue_fail=false;test_now+=100000;drive_all();} ++ else if(cmd && !strcmp(cmd,"send_fail"))send_fail=true; ++ else if(cmd && !strcmp(cmd,"send_resume"))send_fail=false; ++ else if(cmd && !strcmp(cmd,"encode_fail")){barrier_name="request_error_encode";barrier_action=fail_error_encoding;} ++ else if(cmd && !strcmp(cmd,"encode_resume"))fail_allocation=0; ++ else if(cmd && !strcmp(cmd,"write_fail"))driver_write_fail=true; ++ else if(cmd && !strcmp(cmd,"resize_reject"))driver_resize_reject=true; ++ else if(cmd && !strcmp(cmd,"drain"))drive_all(); ++ else { ++ int fd=1;cJSON *f=cJSON_GetObjectItem(j,"fd");if(f)fd=f->valueint; ++ cJSON *msg=cJSON_GetObjectItem(j,"message");char *raw=cJSON_PrintUnformatted(msg);incoming=raw;reqs[fd].method=1;current=(void*)3;int ret=ws_handler(&reqs[fd]);current=(void*)1;incoming=NULL;cJSON_free(raw);assert(ret==0);drive_all(); ++ } ++ if(shell_task.fn && (((ssh_shell_context_t*)shell_task.arg)->disconnect_requested || !ts_ws_op_is_open(((ssh_shell_context_t*)shell_task.arg)->op))){shell_task.fn(shell_task.arg);shell_task.fn=NULL;drive_all();} ++ ts_ws_op_stats_t st;ts_ws_op_stats(TS_WS_OP_SHELL,&st); ++ printf("{\"state\":%d,\"writes\":%d,\"live\":%u,\"channels\":%d,\"refs\":%u,\"preparing\":%u,\"unsettled\":%u}\n",st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j); ++ } ++ return 2; ++} +diff --git a/tests/ws_subscriptions/test_shell_driver.c b/tests/ws_subscriptions/test_shell_driver.c +new file mode 100644 +index 0000000..d6f6f8d +--- /dev/null ++++ b/tests/ws_subscriptions/test_shell_driver.c +@@ -0,0 +1,56 @@ ++#define OP_ADAPTER_NO_MAIN ++#define PROJECT_REAL_DRIVER ++#include "test_operation_adapter.c" ++static unsigned notified; ++static void cli_output(const char *data,size_t len,void *arg){(void)data;(void)len;(void)arg;} ++#define CONFIG_ESP_CONSOLE_UART_NUM 0 ++static unsigned cli_interrupts; ++static int uart_read_bytes(int port,uint8_t *b,size_t n,unsigned wait){(void)port;(void)n;(void)wait;*b=0x1c;return 1;} ++static void cli_request_interrupt(void){cli_interrupts++;} ++static void cli_printf(const char *fmt,...){(void)fmt;} ++#define ts_console_request_interrupt cli_request_interrupt ++#define ts_console_printf cli_printf ++#include "cli_shell_fixture.inc" ++#undef ts_console_request_interrupt ++#undef ts_console_printf ++static void driver_closed_cb(int code,void *arg){(void)code;(void)arg;notified++;} ++static void make_shell(ts_ssh_session_t *session,ts_ssh_shell_t *shell){ ++ ts_ssh_config_t c=TS_SSH_DEFAULT_CONFIG();c.host="192.0.2.1";c.username="u";c.auth.password="p"; ++ assert(ts_ssh_session_create(&c,session)==0 && ts_ssh_connect(*session)==0); ++ assert(ts_ssh_shell_open(*session,NULL,shell)==0); ++} ++static void empty(void){assert(!live_allocations && !driver_channels && !driver_sessions && !driver_sockets);} ++int main(int argc,char **argv){ ++ (void)argv; ++ cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); ++ ts_ssh_session_t session;ts_ssh_shell_t shell;char buf[8];size_t n;int64_t before; ++ if(argc>1 && !strcmp(argv[1],"--cli-exit")){make_shell(&session,&shell);size_t ignored=0;shell_input_callback(&ignored,shell);fprintf(stderr,"CLI exit: active=%d interrupt=%u\n",ts_ssh_shell_is_active(shell),cli_interrupts);assert(!ts_ssh_shell_is_active(shell) && cli_interrupts==1);ts_ssh_shell_close(shell);ts_ssh_session_destroy(session);empty();return 0;} ++ if(argc>1 && !strcmp(argv[1],"--metrics")){unsigned begin=allocations;make_shell(&session,&shell);unsigned opened=allocations;assert(ts_ssh_shell_write(shell,"abc",3,&n)==ESP_OK);unsigned wrote=allocations;assert(ts_ssh_shell_send_signal(shell,"TERM")==ESP_ERR_NOT_SUPPORTED);unsigned rejected=allocations;ts_ssh_shell_close(shell);ts_ssh_session_destroy(session);empty();printf("{\"open_allocations\":%u,\"write_allocations\":%u,\"unsupported_allocations\":%u,\"close_allocations\":%u,\"retained\":%u}\n",opened-begin,wrote-opened,rejected-wrote,allocations-rejected,live_allocations);return 0;} ++ if(argc>1){make_shell(&session,&shell);driver_eof=true;assert(ts_ssh_shell_read(shell,buf,sizeof(buf),&n)==ESP_ERR_INVALID_STATE);assert(ts_ssh_shell_close(shell)==0);ts_ssh_session_destroy(session);fprintf(stderr,"EOF ledger: allocations=%u channels=%d sessions=%d sockets=%d\n",live_allocations,driver_channels,driver_sessions,driver_sockets);empty();return 0;} ++ make_shell(&session,&shell);assert(ts_ssh_shell_read(shell,buf,sizeof(buf),&n)==ESP_ERR_TIMEOUT && ts_ssh_shell_is_active(shell)); ++ ts_ssh_shell_set_close_cb(shell,driver_closed_cb,NULL);driver_eof=true; ++ assert(ts_ssh_shell_poll(shell)==ESP_ERR_INVALID_STATE && notified==1);assert(ts_ssh_shell_close(shell)==0);shell=NULL;assert(notified==1);assert(ts_ssh_session_destroy(session)==0);empty();driver_eof=false; ++ puts("PASS real Shell+client: zero data is not EOF; EOF then close releases wrapper/channel/session/socket; close callback exactly once"); ++ make_shell(&session,&shell);driver_write_fail=true;assert(ts_ssh_shell_write(shell,"x",1,&n)==ESP_FAIL && n==0 && !ts_ssh_shell_is_active(shell));driver_write_fail=false; ++ assert(ts_ssh_shell_close(shell)==0);ts_ssh_session_destroy(session);empty(); ++ make_shell(&session,&shell);driver_partial=true;assert(ts_ssh_shell_write(shell,"abc",3,&n)==ESP_FAIL && n==1 && !ts_ssh_shell_is_active(shell));driver_write_fail=false;ts_ssh_shell_close(shell);ts_ssh_session_destroy(session);empty(); ++ make_shell(&session,&shell);driver_resize_reject=true;assert(ts_ssh_shell_resize(shell,80,24)==ESP_FAIL && ts_ssh_shell_is_active(shell));driver_resize_reject=false;driver_read_fail=true;assert(ts_ssh_shell_read(shell,buf,sizeof(buf),&n)==ESP_FAIL && !ts_ssh_shell_is_active(shell));driver_read_fail=false;ts_ssh_shell_close(shell);ts_ssh_session_destroy(session);empty(); ++ make_shell(&session,&shell);driver_write_again=true;before=test_now;assert(ts_ssh_shell_write(shell,"x",1,&n)==ESP_ERR_TIMEOUT && test_now-before<=1000000);driver_write_again=false; ++ driver_close_again=true;before=test_now;assert(ts_ssh_shell_close(shell)==0 && test_now==before);ts_ssh_session_destroy(session);driver_close_again=false;empty(); ++ puts("PASS real Shell+client: fatal write/timeout retires channel; persistent close EAGAIN falls back to local session teardown without waiting"); ++ for(int phase=1;phase<=4;phase++){ ++ ts_ssh_config_t c=TS_SSH_DEFAULT_CONFIG();c.host="192.0.2.1";c.username="u";c.auth.password="p"; ++ assert(ts_ssh_session_create(&c,&session)==0 && ts_ssh_connect(session)==0);driver_phase=phase;driver_close_again=true;before=test_now;shell=(void*)1; ++ assert(ts_ssh_shell_open(session,NULL,&shell)!=0 && !shell && test_now-before<=10000000);ts_ssh_session_destroy(session);driver_phase=0;driver_close_again=false;empty(); ++ } ++ puts("PASS real Shell+client: partial initialization/open/PTY/shell-start failure and bounded EAGAIN all release owned resources"); ++ make_shell(&session,&shell);before=driver_reads;assert(ts_ssh_shell_run(shell,cli_output,shell_input_callback,shell)==ESP_OK && driver_reads==before && cli_interrupts==1);ts_ssh_shell_close(shell);ts_ssh_session_destroy(session);empty(); ++ puts("PASS Shell run: local exit requested by input callback stops before another network read; close still owns cleanup"); ++ setup();cJSON *j=cJSON_Parse("{\"host\":\"192.0.2.1\",\"user\":\"u\",\"password\":\"p\"}");handle_ssh_connect(&reqs[1],j);cJSON_Delete(j);assert(shell_task.fn);ssh_shell_context_t *ctx=shell_task.arg;ssh_cleanup();shell_resources_close(ctx);shell_resources_close(ctx);shell_task.fn(shell_task.arg);finish_all();empty(); ++ puts("PASS actual WebUI cleanup twice uses cleared handles; original operation/ticket/target and actual lower resources drain"); ++ setup();shell_task.fn=NULL;j=cJSON_Parse("{\"host\":\"192.0.2.1\",\"user\":\"u\",\"password\":\"p\"}");handle_ssh_connect(&reqs[1],j);cJSON_Delete(j);assert(shell_task.fn); ++ ssh_send_output(shell_task.arg,"accepted",8); ++ assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(driver_channels==1 && ts_ws_op_busy()); ++ delay_hook=stop_progress_shell;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL;for(int i=0;i<32;i++)if(reqs[i].sess_ctx)close_peer(i);ts_webui_ws_stopped((void*)11);empty(); ++ puts("PASS real lower resources survive stop timeout; accepted output and terminal drain on retry with no new business message"); ++} +diff --git a/tests/ws_subscriptions/verify_project_assets.py b/tests/ws_subscriptions/verify_project_assets.py +new file mode 100644 +index 0000000..20e4116 +--- /dev/null ++++ b/tests/ws_subscriptions/verify_project_assets.py +@@ -0,0 +1,21 @@ ++#!/usr/bin/env python3 ++"""Verify final optimized/gzip files and reproduce SPIFFS with the fixed SDK.""" ++import gzip,hashlib,json,os,pathlib,subprocess,tempfile ++root=pathlib.Path(__file__).resolve().parents[2] ++build=pathlib.Path(os.environ.get('V3_BUILD','/tmp/tianshan-project-v3-build/build'));web=build/'esp-idf/ts_webui/web_optimized';src=root/'components/ts_webui/web';doc=root/'docs/repair/ws-project-v3' ++sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest() ++result={} ++for rel in ['index.html','js/terminal.js','js/lang/zh-CN.js','js/lang/en-US.js']: ++ p=web/rel;gz=p.with_suffix(p.suffix+'.gz');assert gzip.decompress(gz.read_bytes())==p.read_bytes() ++ if rel.endswith('.js'):subprocess.run(['node','--check',str(p)],check=True) ++ result[rel]={'source_sha256':sha(src/rel),'optimized_sha256':sha(p),'gzip_sha256':sha(gz),'optimized_bytes':p.stat().st_size} ++assert '20260926-shell-contract' in (web/'index.html').read_text() ++assert 'sshControlUnsupported' in (web/'js/terminal.js').read_text() ++with tempfile.TemporaryDirectory(prefix='ts-v3-spiffs-') as d: ++ image=pathlib.Path(d)/'www.bin' ++ cmd=['python3',os.environ['IDF_PATH']+'/components/spiffs/spiffsgen.py','0x300000',str(web),str(image),'--page-size=256','--obj-name-len=32','--meta-len=4','--use-magic','--use-magic-len'] ++ subprocess.run(cmd,check=True);assert image.read_bytes()==(build/'www.bin').read_bytes() ++result['build']={p:{'sha256':sha(build/p),'bytes':(build/p).stat().st_size} for p in ['TianShanOS.bin','www.bin','TianShanOS.elf']} ++result['spiffs_regeneration']='byte-identical from verified optimized directory' ++(doc/'assets.json').write_text(json.dumps(result,indent=2)) ++print('PASS optimized syntax, gzip identity, cache key, and byte-identical SPIFFS reconstruction') +diff --git a/tests/prompts/project-cross.cjs b/tests/prompts/project-cross.cjs +new file mode 100644 +index 0000000..c902f24 +--- /dev/null ++++ b/tests/prompts/project-cross.cjs +@@ -0,0 +1,88 @@ ++/* Bidirectional bridge: final production C frames -> actual JS socket dispatcher -> ++ * actual onData/start/exit requests -> real C ws_handler + operation + SSH drivers. ++ * Network/libssh2/xterm rendering are boundaries; no lifecycle logic is replaced. */ ++const assert=require('node:assert/strict'),{spawn}=require('node:child_process'),readline=require('node:readline'),fs=require('node:fs'); ++const path=require('node:path'),{harness,read:sourceRead}=require('./harness.cjs'); ++const read=file=>process.env.PROJECT_WEB_ROOT?fs.readFileSync(path.join(process.env.PROJECT_WEB_ROOT,file),'utf8'):sourceRead(file); ++async function engine(language,browserMode){ ++ if(!browserMode){const h=harness(language);await h.ready();h.load();await h.run(`i18n.setLanguage('${language}')`);return {run:async s=>h.run(s),close:async()=>{}};} ++ const {chromium}=require('playwright');const browser=await chromium.launch({channel:'chrome',headless:true}); ++ const page=await browser.newPage();const errors=[];page.on('pageerror',err=>errors.push(err.message)); ++ await page.addInitScript(language=>{localStorage.setItem('ts_language',language);window.WebSocket=class{static OPEN=1;static CONNECTING=0;constructor(){this.readyState=0;}send(){}close(){}};},language); ++ await page.route('**/*',async r=>{ ++ const url=new URL(r.request().url());if(url.origin!=='http://fixture.local'){await r.abort();return;} ++ if(url.pathname.startsWith('/api/')){await r.fulfill({json:{code:0,data:{}}});return;} ++ const rel=url.pathname==='/'?'index.html':url.pathname.slice(1); ++ try{await r.fulfill({body:read(rel),contentType:rel.endsWith('.js')?'application/javascript':rel.endsWith('.css')?'text/css':rel.endsWith('.html')?'text/html':'application/octet-stream'});}catch{await r.abort();} ++ }); ++ await page.goto('http://fixture.local/');await page.waitForFunction(()=>i18n.isReady()); ++ await page.evaluate(()=>{const f=document.createElement('div');f.id='fixture';document.body.append(f);}); ++ return {run:s=>page.evaluate(s),close:async()=>{await browser.close();assert.deepEqual(errors,[]);}}; ++} ++async function main(){ ++ const baseline=process.argv.includes('--baseline'),browserMode=process.argv.includes('--browser'); ++ const language=process.env.CROSS_LANGUAGE||'en-US',e=await engine(language,browserMode); ++ let c;const records=[];let exit,err='',pending,chain=Promise.resolve(); ++ try{ ++ await e.run(`window.sent=[];window.lines=[];window.input=null; ++ window.WebSocket=class {static OPEN=1;static CONNECTING=0;constructor(){this.readyState=1;}send(s){sent.push(JSON.parse(s));}close(){this.readyState=3;}}; ++ window.term=new WebTerminal('fixture');term.terminal={write:s=>lines.push(s),writeln:s=>lines.push(s),onData:f=>input=f,dispose:()=>{}}; ++ term.setupInputHandler();term.connect();term.ws.onopen();`); ++ c=spawn('bash',['tests/ws_subscriptions/run_project_bridge.sh'],{cwd:path.resolve(__dirname,'../..'),env:process.env}); ++ c.stderr.on('data',b=>err+=b); ++ const done=new Promise(r=>c.on('close',code=>{exit=code;r(code);if(pending){pending.reject(new Error(err||'C exited '+code));pending=null;}})); ++ readline.createInterface({input:c.stdout}).on('line',line=>{ ++ chain=chain.then(async()=>{const m=JSON.parse(line);records.push(m); ++ if(m.frame && m.fd===1)await e.run(`term.ws.onmessage({data:${JSON.stringify(m.bytes || JSON.stringify(m.frame))}})`); ++ if('state'in m||m.finished){const p=pending;pending=null;p?.resolve(m);} ++ }).catch(error=>{pending?.reject(error);pending=null;}); ++ }); ++ const step=msg=>new Promise((resolve,reject)=>{assert(!pending);pending={resolve,reject};c.stdin.write(JSON.stringify(msg)+'\n');}); ++ const sendNext=async()=>{const message=await e.run('sent.shift()');assert(message,'frontend generated no request');return step({message});}; ++ const start=async()=>{await e.run(`term.startSshShell({host:'192.0.2.1',user:'fake',password:'fake',port:22})`);return sendNext();}; ++ const state=()=>e.run(`({mode:term.sshMode,connecting:term.sshConnecting,restoring:term.restoring,connected:term.connected,lines:[...lines],sent:[...sent]})`); ++ await sendNext();await start();assert((await state()).mode); ++ const before=(await state()).lines.length;const afterSignal=await step({message:{type:'ssh_signal',signal:'TERM'}}); ++ const s=await state();const recovered=s.mode&&!s.restoring&&!s.lines.slice(before).some(x=>x==='tianshan> '); ++ await e.run(`input('x\\r')`);const next=await e.run('sent.shift()'); ++ if(baseline){assert(!recovered && next.type!=='ssh_input');await step({cmd:'finish'});await done;assert.equal(exit,0,err);console.log('CONFIRMED H1: actual C request error leaves op OPEN but JS exits SSH and next input is not routed to SSH');return;} ++ assert(recovered,'request failure changed active SSH mode/prompt/recovery');assert.equal(next.type,'ssh_input'); ++ let cs=await step({message:next});assert.equal(cs.writes,afterSignal.writes+1,'next frontend input must execute on original C Shell'); ++ for(const message of [{type:'ssh_resize',width:0,height:20},{type:'ssh_resize',width:80.5,height:20}]){await step({message});assert((await state()).mode);} ++ await step({cmd:'resize_reject'});await step({message:{type:'ssh_resize',width:80,height:24}});assert((await state()).mode);await step({cmd:'reset_driver'}); ++ // Another page cannot input, disconnect, signal or resize the current owner. ++ const n=cs.writes;for(const message of [{type:'ssh_input',data:'wrong'},{type:'ssh_disconnect'},{type:'ssh_signal',signal:'INT'},{type:'ssh_resize',width:80,height:24},{type:'ssh_connect',host:'192.0.2.2',user:'other'}]){cs=await step({fd:2,message});assert.equal(cs.writes,n);assert.equal(cs.channels,1);assert((await state()).mode);} ++ // A rejected duplicate start on the owner also must not terminate its live op. ++ await step({message:{type:'ssh_connect',host:'192.0.2.1',user:'fake'}});assert((await state()).mode); ++ await e.run(`input('\\x1c')`);await sendNext();assert(!(await state()).mode);assert((await state()).connected); ++ await e.run(`input('help\\r')`);const local=await e.run('sent.shift()');assert.equal(local.type,'terminal_input');await step({message:local}); ++ await step({message:{type:'terminal_stop'}});await e.run(`input('help\\r')`);await sendNext();assert((await state()).restoring); ++ const restore=await e.run('sent.shift()');assert.equal(restore.type,'terminal_start');await step({message:restore});assert((await state()).connected && !(await state()).restoring); ++ await start();assert((await state()).mode);await step({cmd:'write_fail'});await e.run(`input('x')`);await sendNext();assert(!(await state()).mode);assert(!(await state()).restoring);assert((await state()).lines.some(x=>/unconfirmed|尚未确认/.test(x))); ++ await step({cmd:'reset_driver'});await start();assert((await state()).mode);await step({cmd:'eof'});assert(!(await state()).mode); ++ await step({cmd:'reset_driver'});await step({cmd:'setup_fail'});await start();assert(!(await state()).mode && !(await state()).connecting);await step({cmd:'reset_driver'});await start();assert((await state()).mode); ++ // Failed notification encoding does not change active request ownership. ++ await step({cmd:'encode_fail'});await step({message:{type:'ssh_signal',signal:'TERM'}});await step({cmd:'encode_resume'});assert((await state()).mode);await e.run(`input('z')`);await sendNext(); ++ // A control failure crosses output preparation and a genuine close: exactly one terminal, ++ // queued output precedes it, then next frontend action is local (no automatic replay). ++ const crossing=records.length;await step({cmd:'error_close'});await step({message:{type:'ssh_signal',signal:'TERM'}});assert(!(await state()).mode); ++ const crossed=records.slice(crossing).filter(r=>r.frame&&r.fd===1).map(r=>r.frame); ++ assert.equal(crossed.filter(f=>f.type==='ssh_status'&&f.status==='closed').length,1); ++ assert(crossed.findIndex(f=>f.type==='ssh_output')f.type==='ssh_status'&&f.status==='closed')); ++ await start();assert((await state()).mode); ++ // Direct request notification send failure cannot recursively change the operation. ++ await step({cmd:'send_fail'});await step({message:{type:'ssh_signal',signal:'TERM'}});await step({cmd:'send_resume'});assert((await state()).mode); ++ await e.run(`input('q')`);await sendNext(); ++ // Output accepted while HTTPD is unavailable follows the existing original-operation ++ // failure path; capacity recovers with no new business input, and resources settle. ++ await step({cmd:'queue_fail'});await step({cmd:'output'});await step({cmd:'queue_resume'});assert(!(await state()).mode); ++ await step({cmd:'finish'});await done;assert.equal(exit,0,err); ++ // Old socket frames/close and callbacks after destroy cannot change new instance. ++ const stale=await e.run(`(()=>{const old=term.ws;term.connect();term.connected=true;term.sshMode=true;const fresh=term.ws;old.onmessage({data:JSON.stringify({type:'ssh_status',status:'error'})});old.onclose({code:1006});const held=term.sshMode&&term.connected&&term.ws===fresh;term.destroy();fresh.onmessage({data:JSON.stringify({type:'connected'})});return held&&!term.connected;})()`);assert(stale); ++ console.log(`PASS ${browserMode?'Chrome':'Node'} ${language}: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero`); ++ }finally{ ++ if(process.env.CROSS_OUTPUT)fs.writeFileSync(process.env.CROSS_OUTPUT,JSON.stringify({records,stderr:err,exit},null,2)); ++ if(c && exit===undefined)c.kill('SIGTERM');await e.close(); ++ } ++} ++main().catch(e=>{console.error(e);process.exitCode=1;}); diff --git a/docs/repair/ws-project-v3/cumulative-files.txt b/docs/repair/ws-project-v3/cumulative-files.txt new file mode 100644 index 0000000..0b9f186 --- /dev/null +++ b/docs/repair/ws-project-v3/cumulative-files.txt @@ -0,0 +1,340 @@ + .github/workflows/build.yml | 43 +- + .gitignore | 3 + + build/TianShanOS.bin | Bin 2154096 -> 2161568 bytes + build/www.bin | Bin 3145728 -> 3145728 bytes + .../ch405labs_esp_libssh2/libssh2/src/mbedtls.c | 2 +- + .../ch405labs_esp_libssh2/libssh2/src/userauth.c | 2 +- + components/ts_api/CMakeLists.txt | 2 +- + components/ts_api/src/ts_api_automation.c | 1067 ++---- + components/ts_api/src/ts_api_cert.c | 110 +- + components/ts_api/src/ts_api_ssh.c | 215 +- + components/ts_automation/CMakeLists.txt | 2 + + .../ts_automation/include/ts_action_manager.h | 10 + + .../ts_automation/include/ts_automation_types.h | 12 +- + components/ts_automation/include/ts_rule_codec.h | 14 + + components/ts_automation/include/ts_rule_engine.h | 13 +- + components/ts_automation/src/ts_action_manager.c | 585 ++-- + components/ts_automation/src/ts_automation.c | 120 +- + components/ts_automation/src/ts_rule_codec.c | 502 +++ + components/ts_automation/src/ts_rule_engine.c | 1959 ++++------- + components/ts_automation/src/ts_rule_store.c | 400 +++ + components/ts_automation/src/ts_rule_store.h | 11 + + components/ts_cert/CMakeLists.txt | 1 + + components/ts_cert/include/ts_cert.h | 49 +- + components/ts_cert/include/ts_cert_time.h | 17 + + components/ts_cert/src/ts_cert.c | 913 +++-- + components/ts_cert/src/ts_cert_time.c | 42 + + components/ts_console/commands/ts_cmd_auto.c | 1 + + components/ts_console/commands/ts_cmd_pki.c | 17 +- + components/ts_console/commands/ts_cmd_ssh.c | 15 +- + components/ts_core/ts_event/include/ts_event.h | 9 + + components/ts_core/ts_event/src/ts_event.c | 210 +- + components/ts_core/ts_log/include/ts_log.h | 2 + + components/ts_core/ts_log/src/ts_log.c | 443 +-- + components/ts_core/ts_log/src/ts_log_preview.h | 59 + + components/ts_core/ts_service/src/ts_service.c | 13 +- + components/ts_https/include/ts_https.h | 13 + + components/ts_https/src/ts_https.c | 164 +- + components/ts_https/src/ts_https_auth.c | 25 +- + components/ts_net/include/ts_http_server.h | 6 + + components/ts_net/src/ts_http_server.c | 55 +- + components/ts_net/src/ts_time_sync.c | 13 +- + components/ts_pki_client/src/ts_pki_client.c | 83 +- + components/ts_security/CMakeLists.txt | 2 + + components/ts_security/Kconfig | 8 + + components/ts_security/include/ts_ssh_client.h | 10 +- + components/ts_security/include/ts_ssh_log_watch.h | 9 +- + components/ts_security/include/ts_ssh_probe.h | 17 + + components/ts_security/include/ts_ssh_service.h | 57 + + components/ts_security/src/ts_security.c | 6 + + components/ts_security/src/ts_ssh_client.c | 960 ++---- + .../ts_security/src/ts_ssh_commands_config.c | 81 +- + components/ts_security/src/ts_ssh_hosts_config.c | 65 +- + components/ts_security/src/ts_ssh_log_watch.c | 739 ++-- + components/ts_security/src/ts_ssh_probe.c | 63 + + components/ts_security/src/ts_ssh_service.c | 646 ++++ + components/ts_webui/CMakeLists.txt | 4 +- + components/ts_webui/include/ts_ws_operation.h | 61 + + components/ts_webui/include/ts_ws_subscriptions.h | 21 +- + components/ts_webui/include/ts_ws_transport.h | 131 + + components/ts_webui/src/ts_webui.c | 16 +- + components/ts_webui/src/ts_webui_ws.c | 1503 ++++---- + components/ts_webui/src/ts_ws_operation.c | 276 ++ + components/ts_webui/src/ts_ws_subscriptions.c | 1046 +++--- + components/ts_webui/src/ts_ws_transport.c | 658 ++++ + components/ts_webui/web/index.html | 169 +- + components/ts_webui/web/js/api.js | 113 +- + components/ts_webui/web/js/app.js | 3100 +++++++++-------- + components/ts_webui/web/js/lang/en-US.js | 368 +- + components/ts_webui/web/js/lang/zh-CN.js | 338 +- + components/ts_webui/web/js/router.js | 79 +- + components/ts_webui/web/js/terminal.js | 87 +- + docs/CERTIFICATE_FIX_REPORT.md | 254 ++ + docs/OS_RUNTIME_AUDIT_2026-09-23.md | 145 + + docs/PROMPT_REPAIR_REPORT.md | 34 + + docs/releases/v0.5.2-validation.md | 51 + + docs/releases/v0.5.2.md | 69 + + docs/repair/ws-control/README.md | 79 + + docs/repair/ws-control/adapter-tests.txt | 13 + + docs/repair/ws-control/baseline-adapter.c | 287 ++ + docs/repair/ws-control/baseline-control.c | 20 + + docs/repair/ws-control/baseline-evidence.json | 6 + + docs/repair/ws-control/baseline-results.txt | 3 + + docs/repair/ws-control/baseline.json | 81 + + docs/repair/ws-control/baseline.tar.gz | Bin 0 -> 935282 bytes + docs/repair/ws-control/build-artifacts.json | 10 + + docs/repair/ws-control/build.txt | 30 + + docs/repair/ws-control/certificate-tests.txt | 9 + + docs/repair/ws-control/changes.json | 18 + + docs/repair/ws-control/changes.patch | 862 +++++ + docs/repair/ws-control/control-contract.md | 28 + + docs/repair/ws-control/control-tests.txt | 5 + + docs/repair/ws-control/current-v1.txt | 1 + + docs/repair/ws-control/current-v2.txt | 1 + + docs/repair/ws-control/diff-check.txt | 1 + + docs/repair/ws-control/f1-f2-tests.txt | 23 + + docs/repair/ws-control/historical-f1-f2.txt | 4 + + docs/repair/ws-control/historical-g1-g2.txt | 4 + + docs/repair/ws-control/host-tests.txt | 23 + + docs/repair/ws-control/operation-tests.txt | 2 + + docs/repair/ws-control/publication-adapter.txt | 13 + + docs/repair/ws-control/publication-control.txt | 5 + + docs/repair/ws-control/publication-f1f2.txt | 23 + + docs/repair/ws-control/publication-gate.md | 13 + + docs/repair/ws-control/publication-reviewer.txt | 15 + + docs/repair/ws-control/publication-webui.txt | 51 + + docs/repair/ws-control/resources.txt | 300 ++ + docs/repair/ws-control/reviewer-tests.txt | 15 + + docs/repair/ws-control/runtime-tests.txt | 13 + + docs/repair/ws-control/webui-browser-tests.txt | 56 + + docs/repair/ws-control/webui-node-tests.txt | 51 + + docs/repair/ws-control/working-tree-status.txt | 15 + + docs/repair/ws-f1-f2/README.md | 101 + + docs/repair/ws-f1-f2/after.txt | 23 + + docs/repair/ws-f1-f2/baseline.json | 96 + + docs/repair/ws-f1-f2/before.txt | 4 + + docs/repair/ws-f1-f2/browser.txt | 56 + + docs/repair/ws-f1-f2/build.txt | 33 + + docs/repair/ws-f1-f2/certificate.txt | 9 + + docs/repair/ws-f1-f2/changes.patch | 1012 ++++++ + docs/repair/ws-f1-f2/diff-check.txt | 2 + + docs/repair/ws-f1-f2/final-manifest.json | 41 + + docs/repair/ws-f1-f2/host.txt | 25 + + docs/repair/ws-f1-f2/pr-update-gate.md | 11 + + docs/repair/ws-f1-f2/pr-update-regression.txt | 23 + + docs/repair/ws-f1-f2/pr-update-release.txt | 5 + + docs/repair/ws-f1-f2/pr-update-reviewer.txt | 17 + + docs/repair/ws-f1-f2/pre-fix-source.tar.gz | Bin 0 -> 961554 bytes + docs/repair/ws-f1-f2/prompts.txt | 51 + + docs/repair/ws-f1-f2/resources.txt | 18 + + docs/repair/ws-f1-f2/reviewer.txt | 17 + + docs/repair/ws-f1-f2/runtime.txt | 13 + + docs/repair/ws-operation/README.md | 120 + + docs/repair/ws-operation/adapter-tests.txt | 13 + + docs/repair/ws-operation/baseline-g1-g2.txt | 4 + + docs/repair/ws-operation/baseline.json | 125 + + docs/repair/ws-operation/baseline.tar.gz | Bin 0 -> 1007908 bytes + docs/repair/ws-operation/build-artifacts.json | 10 + + docs/repair/ws-operation/build.txt | 33 + + docs/repair/ws-operation/certificate-tests.txt | 9 + + docs/repair/ws-operation/changes.json | 29 + + docs/repair/ws-operation/changes.patch | 3215 ++++++++++++++++++ + docs/repair/ws-operation/design.md | 50 + + docs/repair/ws-operation/diff-check.txt | 1 + + docs/repair/ws-operation/f1-f2-tests.txt | 23 + + docs/repair/ws-operation/historical-f1-f2.txt | 4 + + docs/repair/ws-operation/host-tests.txt | 23 + + docs/repair/ws-operation/operation-tests.txt | 2 + + docs/repair/ws-operation/public-headers.json | 46 + + docs/repair/ws-operation/publication-adapter.txt | 13 + + docs/repair/ws-operation/publication-f1f2.txt | 23 + + docs/repair/ws-operation/publication-gate.md | 20 + + docs/repair/ws-operation/publication-operation.txt | 2 + + docs/repair/ws-operation/publication-release.txt | 5 + + docs/repair/ws-operation/publication-reviewer.txt | 15 + + docs/repair/ws-operation/resources.txt | 369 ++ + docs/repair/ws-operation/reviewer-tests.txt | 15 + + docs/repair/ws-operation/runtime-tests.txt | 13 + + docs/repair/ws-operation/webui-browser-tests.txt | 56 + + docs/repair/ws-operation/webui-node-tests.txt | 51 + + docs/repair/ws-operation/working-tree-status.txt | 26 + + docs/repair/ws-subscriptions/README.md | 116 + + docs/repair/ws-subscriptions/changes.patch | 3573 ++++++++++++++++++++ + .../evidence/allocation-finding.txt | 3 + + .../ws-subscriptions/evidence/baseline-red.txt | 14 + + .../repair/ws-subscriptions/evidence/baseline.json | 11 + + docs/repair/ws-subscriptions/evidence/browser.txt | 46 + + docs/repair/ws-subscriptions/evidence/build.txt | 10 + + .../ws-subscriptions/evidence/certificate.txt | 9 + + .../ws-subscriptions/evidence/diff-check.txt | 1 + + .../ws-subscriptions/evidence/final-manifest.json | 39 + + docs/repair/ws-subscriptions/evidence/host.txt | 25 + + docs/repair/ws-subscriptions/evidence/prompts.txt | 46 + + .../repair/ws-subscriptions/evidence/resources.txt | 17 + + docs/repair/ws-subscriptions/evidence/runtime.txt | 13 + + docs/repair/ws-subscriptions/evidence/tsan.txt | 1 + + docs/repair/ws-subscriptions/pr-update-gate.md | 19 + + docs/repair/ws-subscriptions/pr-update-host.txt | 25 + + .../repair/ws-subscriptions/pr-update-reviewer.txt | 17 + + .../ws-subscriptions/reviewer-fixes/README.md | 73 + + .../reviewer-fixes/baseline-r1-r3.txt | 3 + + .../reviewer-fixes/baseline-r4-r5.txt | 11 + + .../reviewer-fixes/baseline-replay.txt | 14 + + .../ws-subscriptions/reviewer-fixes/baseline.json | 42 + + .../ws-subscriptions/reviewer-fixes/browser.txt | 56 + + .../ws-subscriptions/reviewer-fixes/build.txt | 30 + + .../reviewer-fixes/certificate.txt | 9 + + .../ws-subscriptions/reviewer-fixes/diff-check.txt | 2 + + .../reviewer-fixes/final-manifest.json | 94 + + .../ws-subscriptions/reviewer-fixes/host.txt | 25 + + .../reviewer-fixes/pre-fix-source.tar.gz | Bin 0 -> 68524 bytes + .../ws-subscriptions/reviewer-fixes/prompts.txt | 51 + + .../ws-subscriptions/reviewer-fixes/resources.txt | 21 + + .../reviewer-fixes/reviewer-fixes.patch | 1830 ++++++++++ + .../reviewer-fixes/reviewer-tests.txt | 17 + + .../ws-subscriptions/reviewer-fixes/runtime.txt | 13 + + .../reviewer-fixes/ts-review-ws-round2/core_stop.c | 53 + + .../ts-review-ws-round2/evidence.txt | 11 + + .../reviewer-fixes/ts-review-ws-round2/review.md | 45 + + .../reviewer-fixes/ts-review-ws-round2/run.sh | 11 + + .../ts-review-ws-round2/service_stop.c | 161 + + .../ts-review-ws-round2/starvation.c | 13 + + .../reviewer-fixes/ts-review-ws/evidence.txt | 3 + + .../reviewer-fixes/ts-review-ws/review.c | 200 ++ + .../reviewer-fixes/ts-review-ws/review.md | 48 + + .../reviewer-fixes/ts-review-ws/run.sh | 7 + + docs/runtime-repair/IMPLEMENTATION_REPORT.md | 64 + + docs/runtime-repair/REVIEW_FIXES_REPORT.md | 57 + + docs/runtime-repair/VERIFICATION.md | 83 + + docs/runtime-repair/baseline-notes.md | 17 + + docs/runtime-repair/evidence/artifacts.json | 26 + + docs/runtime-repair/evidence/build-summary.txt | 8 + + docs/runtime-repair/evidence/certificate-tests.log | 9 + + docs/runtime-repair/evidence/host-tests.log | 9 + + docs/runtime-repair/evidence/resource-sizeof.txt | 16 + + .../evidence/reviewer-fixes/build-source-check.txt | 1 + + .../evidence/reviewer-fixes/certificate.log | 9 + + .../evidence/reviewer-fixes/configuration.log | 1 + + .../evidence/reviewer-fixes/resource-sizeof.txt | 7 + + .../evidence/reviewer-fixes/runtime.log | 13 + + .../evidence/reviewer-fixes/ui-final.log | 1 + + .../runtime-repair/evidence/web-artifact-check.txt | 3 + + main/ts_core_init.c | 81 +- + main/ts_https_retry.h | 27 + + main/ts_services.c | 285 +- + sdkconfig | 1 + + tests/certificate/README.md | 68 + + tests/certificate/extract_lifecycle.py | 27 + + tests/certificate/generate_fixtures.py | 30 + + tests/certificate/run_host.sh | 26 + + tests/certificate/stubs/esp_err.h | 1 + + tests/certificate/stubs/esp_heap_caps.h | 1 + + tests/certificate/stubs/esp_http_server.h | 18 + + tests/certificate/stubs/esp_https_server.h | 10 + + tests/certificate/stubs/esp_log.h | 1 + + tests/certificate/stubs/esp_netif.h | 1 + + tests/certificate/stubs/esp_tls.h | 1 + + tests/certificate/stubs/freertos/FreeRTOS.h | 1 + + tests/certificate/stubs/freertos/semphr.h | 1 + + tests/certificate/stubs/lwip/inet.h | 1 + + tests/certificate/stubs/nvs.h | 1 + + tests/certificate/stubs/nvs_flash.h | 1 + + tests/certificate/stubs/platform.h | 64 + + tests/certificate/stubs/ts_core.h | 1 + + tests/certificate/stubs/ts_crypto.h | 1 + + tests/certificate/stubs/ts_event.h | 1 + + tests/certificate/stubs/ts_time_sync.h | 1 + + tests/certificate/test_api.c | 42 + + tests/certificate/test_coordinator.c | 75 + + tests/certificate/test_lifecycle.c | 46 + + tests/certificate/test_material.c | 131 + + tests/certificate/test_service_stop.c | 44 + + tests/certificate/test_service_stop.sh | 34 + + tests/certificate/test_time_cancel.c | 39 + + tests/certificate/test_time_retry.c | 47 + + tests/certificate/test_ui.cjs | 42 + + tests/prompts/README.md | 21 + + tests/prompts/browser.test.cjs | 132 + + tests/prompts/harness.cjs | 51 + + tests/prompts/ownership.browser.test.cjs | 303 ++ + tests/prompts/package-lock.json | 59 + + tests/prompts/package.json | 15 + + tests/prompts/regression.test.cjs | 171 + + tests/prompts/static.test.cjs | 28 + + tests/release/test_release.py | 57 + + tests/runtime/README.md | 7 + + tests/runtime/extract_engine.py | 9 + + tests/runtime/run_all.sh | 16 + + tests/runtime/run_codec.sh | 9 + + tests/runtime/run_engine.sh | 10 + + tests/runtime/run_log.sh | 20 + + tests/runtime/run_service_watch.sh | 11 + + tests/runtime/run_ssh.sh | 8 + + tests/runtime/run_store.sh | 9 + + tests/runtime/ssh_stubs/esp_timer.h | 3 + + tests/runtime/ssh_stubs/freertos/FreeRTOS.h | 1 + + tests/runtime/ssh_stubs/freertos/task.h | 1 + + tests/runtime/ssh_stubs/ts_core.h | 5 + + tests/runtime/state_stubs/esp_err.h | 3 + + tests/runtime/state_stubs/freertos/FreeRTOS.h | 8 + + tests/runtime/state_stubs/freertos/semphr.h | 3 + + tests/runtime/state_stubs/freertos/task.h | 7 + + tests/runtime/stubs/esp_heap_caps.h | 6 + + tests/runtime/stubs/nvs.h | 6 + + tests/runtime/test_codec.c | 33 + + tests/runtime/test_completion.py | 55 + + tests/runtime/test_configuration_protocol.py | 53 + + tests/runtime/test_engine.c | 77 + + tests/runtime/test_log.c | 115 + + tests/runtime/test_probe.py | 21 + + tests/runtime/test_rule_reload.py | 36 + + tests/runtime/test_service_protocol.c | 147 + + tests/runtime/test_service_watch.c | 64 + + tests/runtime/test_ssh.c | 89 + + tests/runtime/test_stop_protocol.py | 78 + + tests/runtime/test_store.c | 81 + + tests/runtime/test_ui.cjs | 31 + + tests/ws_subscriptions/README.md | 37 + + .../ws_subscriptions/baseline_operation_adapter.c | 163 + + tests/ws_subscriptions/replay_control_baseline.py | 21 + + .../ws_subscriptions/replay_operation_baseline.py | 42 + + tests/ws_subscriptions/run_baseline.sh | 29 + + tests/ws_subscriptions/run_control.sh | 18 + + tests/ws_subscriptions/run_f1_f2.sh | 36 + + tests/ws_subscriptions/run_host.sh | 40 + + tests/ws_subscriptions/run_operation.sh | 9 + + tests/ws_subscriptions/run_operation_adapter.sh | 11 + + tests/ws_subscriptions/run_reviewer.sh | 30 + + tests/ws_subscriptions/run_reviewer_baseline.sh | 27 + + tests/ws_subscriptions/stubs/esp_console.h | 2 + + tests/ws_subscriptions/stubs/esp_err.h | 1 + + tests/ws_subscriptions/stubs/esp_heap_caps.h | 1 + + tests/ws_subscriptions/stubs/esp_http_server.h | 1 + + tests/ws_subscriptions/stubs/esp_log.h | 1 + + tests/ws_subscriptions/stubs/esp_timer.h | 1 + + tests/ws_subscriptions/stubs/freertos/FreeRTOS.h | 1 + + tests/ws_subscriptions/stubs/freertos/queue.h | 1 + + tests/ws_subscriptions/stubs/freertos/semphr.h | 1 + + tests/ws_subscriptions/stubs/freertos/task.h | 1 + + tests/ws_subscriptions/stubs/freertos/timers.h | 12 + + tests/ws_subscriptions/stubs/platform.h | 119 + + tests/ws_subscriptions/stubs/ts_api.h | 1 + + tests/ws_subscriptions/stubs/ts_event.h | 1 + + tests/ws_subscriptions/stubs/ts_log.h | 1 + + tests/ws_subscriptions/stubs/ts_webui.h | 1 + + tests/ws_subscriptions/test_baseline.c | 25 + + tests/ws_subscriptions/test_control.c | 142 + + tests/ws_subscriptions/test_event.c | 59 + + tests/ws_subscriptions/test_f1_f2.c | 107 + + tests/ws_subscriptions/test_init.c | 68 + + tests/ws_subscriptions/test_lifecycle.c | 35 + + tests/ws_subscriptions/test_manager.c | 212 ++ + tests/ws_subscriptions/test_operation.c | 58 + + tests/ws_subscriptions/test_operation_adapter.c | 287 ++ + tests/ws_subscriptions/test_reviewer.c | 55 + + tests/ws_subscriptions/test_reviewer_core.c | 51 + + tests/ws_subscriptions/test_reviewer_http.c | 23 + + tests/ws_subscriptions/test_reviewer_service.c | 30 + + tools/check_release.py | 22 + + version.txt | 2 +- + 339 files changed, 30581 insertions(+), 7726 deletions(-) diff --git a/docs/repair/ws-project-v3/current-allocation-metrics.json b/docs/repair/ws-project-v3/current-allocation-metrics.json new file mode 100644 index 0000000..6d5f009 --- /dev/null +++ b/docs/repair/ws-project-v3/current-allocation-metrics.json @@ -0,0 +1 @@ +{"open_allocations":5,"write_allocations":0,"unsupported_allocations":0,"close_allocations":0,"retained":0} diff --git a/docs/repair/ws-project-v3/current-cli-exit.txt b/docs/repair/ws-project-v3/current-cli-exit.txt new file mode 100644 index 0000000..6e5503c --- /dev/null +++ b/docs/repair/ws-project-v3/current-cli-exit.txt @@ -0,0 +1 @@ +CLI exit: active=0 interrupt=1 diff --git a/docs/repair/ws-project-v3/current-eof-release.txt b/docs/repair/ws-project-v3/current-eof-release.txt new file mode 100644 index 0000000..0e095a0 --- /dev/null +++ b/docs/repair/ws-project-v3/current-eof-release.txt @@ -0,0 +1 @@ +EOF ledger: allocations=0 channels=0 sessions=0 sockets=0 diff --git a/docs/repair/ws-project-v3/diff-check.txt b/docs/repair/ws-project-v3/diff-check.txt new file mode 100644 index 0000000..0c564d3 --- /dev/null +++ b/docs/repair/ws-project-v3/diff-check.txt @@ -0,0 +1 @@ +PASS git diff --check diff --git a/docs/repair/ws-project-v3/final-inputs.json b/docs/repair/ws-project-v3/final-inputs.json new file mode 100644 index 0000000..016a622 --- /dev/null +++ b/docs/repair/ws-project-v3/final-inputs.json @@ -0,0 +1,853 @@ +{ + "head": "568b871f64902f88b3c68148ce072eda218fe9db", + "branch": "fix/v0.5.2-reliability-and-prompts", + "sdk_head": "30aaf64524299d3bde422ca9a2848090d1bc5d0f", + "build_command": "idf.py -B /tmp/tianshan-project-v3-build/build -D SDKCONFIG=/tmp/tianshan-project-v3-build/sdkconfig build", + "build_sdkconfig_sha256": "1340e033b5865e39dd6b8c3516dffb27d01da5aff41127c69b583cbfb99acef0", + "created_utc": "2026-09-26T15:50:46.400805+00:00", + "sha256": { + "CMakeLists.txt": "73a24128dd9cb60d9e980787b80ec9f32e3b9f0b873c83ef17ee8ee75152fecf", + "components/ch405labs_esp_libssh2/.gitmodules": "467fd072f917e5068f5b2a846127b7b82f386fb5b238156aedf38cce2631ab9f", + "components/ch405labs_esp_libssh2/CMakeLists.txt": "defbc67e892a2dc88a98689c81d71703c494df741da1281a971a32c19d71ffef", + "components/ch405labs_esp_libssh2/README.md": "d4baa8a5f5b154b4c4543c11f32300572b3acdebc26c613749be1cc5957b1679", + "components/ch405labs_esp_libssh2/libssh2/.editorconfig": "286f4ce9ddba0c0725cc4d37055e5988ac22c61c1b36bb6ee1a6a895d419f411", + "components/ch405labs_esp_libssh2/libssh2/.gitattribute": "50641866adaa8d562ba65baca87f2f3ce91f61ca40fc21753fe8f35d6013befc", + "components/ch405labs_esp_libssh2/libssh2/.github/ISSUE_TEMPLATE/bug_report.md": "bc14bd2401eb9dfb7a3d762adffd5e455817705f387800ea7b6c38c1f1408633", + "components/ch405labs_esp_libssh2/libssh2/.github/SECURITY.md": "e694a8bc825fde44c30c1bd56465a04872a901406bb83c83055d20bb592485d9", + "components/ch405labs_esp_libssh2/libssh2/.github/stale.yml": "25a2e801cd260d70243072d3e5506c511bd720f3f6ef9fd7fa007b7d1c7ea8e1", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/appveyor_docker.yml": "da1c0951a12c434f05836f1789f15961c6fcabc603e647430a05a34b0424a24b", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/appveyor_status.yml": "4c5246d62039581107a7d02ce6e6add044316c0b74c1539a6e14b184d50fc52a", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/ci.yml": "5fa3a7f5a9fa332495ea33881713679ff28330a367cc4323488a987a3125ea9d", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/cifuzz.yml": "84b5ae690289c4db4b8cdd1907e7a3d63c8df5c3cc1ddd2d43633df7821b2e5e", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/openssh_server.yml": "0cf892551ec733d936325e69d4a4384666fd61c0227c39bb74887d805b180cdb", + "components/ch405labs_esp_libssh2/libssh2/.gitignore": "6c7cfd1ecdb57b89fc5b0fadc59727fd6cd3ed803e448e5811b785e54acd1a6a", + "components/ch405labs_esp_libssh2/libssh2/.travis.yml": "0230a26255749c26837b5dc54c9811565a1f2092bca181db030255d0d857769f", + "components/ch405labs_esp_libssh2/libssh2/CMakeLists.txt": "2798ced9569334a34eee6fed8037cc69d5a3b6b3af6ccb8f27fac5f6b39dc4b7", + "components/ch405labs_esp_libssh2/libssh2/COPYING": "859e60d760a3446ecaf777339f1eef98c527aea40714384d24b882a83ffdd23a", + "components/ch405labs_esp_libssh2/libssh2/Makefile.OpenSSL.inc": "8e82af68b172ddccf94c65c1b4e38b69b3b7f027cc14a54b6d660c5f2bcd4de9", + "components/ch405labs_esp_libssh2/libssh2/Makefile.WinCNG.inc": "79243be1029a0df52a5e79b3dceb80ac462f2e735e25445e38852610bee62f34", + "components/ch405labs_esp_libssh2/libssh2/Makefile.am": "af1c3b9cc5b46c35fc5556a458b819ca320bfd2646ff13d2bbc3fa0bf21e658d", + "components/ch405labs_esp_libssh2/libssh2/Makefile.inc": "69ed9dd108033552385a3b6257f47d1cece33490fec25c14ef208b3b8f9c9273", + "components/ch405labs_esp_libssh2/libssh2/Makefile.libgcrypt.inc": "3d71dbe94c906d07c70eb8c7eae80fe5ae014565d7a9446bd39b659e91b73b71", + "components/ch405labs_esp_libssh2/libssh2/Makefile.mbedTLS.inc": "18bf8364aaef158a27b65be88ac1fd74af0cbd336930b6ce611b62dab77feebc", + "components/ch405labs_esp_libssh2/libssh2/Makefile.os400qc3.inc": "ac9b0e1731f7dfa20e3987e108a4c5896e6095638ec545c8f2ac64c35b63a455", + "components/ch405labs_esp_libssh2/libssh2/Makefile.wolfSSL.inc": "d6288360c49d5246ba3757304e2c4850d96651d7dfe2d2583a8bee2fe9313665", + "components/ch405labs_esp_libssh2/libssh2/NEWS": "9418b9c8dcafc633c2c16372b2b21ceb70a06243756af21eff173a4b379101d1", + "components/ch405labs_esp_libssh2/libssh2/NMakefile": "2d1cbda9bccd886de3c99dae77f09ac75a7f09f1834272b4a9154d2a0ae9a81a", + "components/ch405labs_esp_libssh2/libssh2/README": "41df43a8f24ec77082fc4c4609bd54b17e0a610e6bb319171ec1fd4d31a24d02", + "components/ch405labs_esp_libssh2/libssh2/README.md": "d7595097b84462de1f273ed1628315f47b23dfaff070af2bfb14f38e22ec13b8", + "components/ch405labs_esp_libssh2/libssh2/RELEASE-NOTES": "9a88e3e26281797ee09f09cd04e4bd753837b02366dcaf34885b800742bc862f", + "components/ch405labs_esp_libssh2/libssh2/acinclude.m4": "c461e884733a19f15b603aec9ac590218ec0fd93e34cd48b279e2f0af5dc70f3", + "components/ch405labs_esp_libssh2/libssh2/appveyor.yml": "984dffbbd4503ebd67359d660d51198c420dab745efef074fbae126aa3fa8492", + "components/ch405labs_esp_libssh2/libssh2/buildconf": "c2102a17b8f50f0d56d20639c05c70347a4e6ac5dcec351c6f851371e2a68a71", + "components/ch405labs_esp_libssh2/libssh2/ci/appveyor/docker-bridge.bat": "f72fdb40e7a9c3aa5c5fe5fd6a4a008463f1f3b991e0875f19eb5a9a2e8fa3cf", + "components/ch405labs_esp_libssh2/libssh2/ci/appveyor/docker-bridge.ps1": "e8947a221954fd55ac060300bf71b512869a087694f4116ad40ffcfa5ede8160", + "components/ch405labs_esp_libssh2/libssh2/ci/checksrc.pl": "879e805b57e2e86f6894a6a4e395daf1c1c048ee5984e109be74afc750782567", + "components/ch405labs_esp_libssh2/libssh2/ci/checksrc.sh": "a435be07f99eaac5b59f9cf68d88e3541c9fbed09177d0874078c22547edd5e9", + "components/ch405labs_esp_libssh2/libssh2/cmake/CheckFunctionExistsMayNeedLibrary.cmake": "60a8d1afe9a3b71cedb782ac6187a9a041d2792006a7eb3379bc42a9fcb95a4d", + "components/ch405labs_esp_libssh2/libssh2/cmake/CheckNonblockingSocketSupport.cmake": "443b9824a1d7f7cc0a9c1b740ca9824f82f73ac7f0294aa2c1e3192aa3cb5e0d", + "components/ch405labs_esp_libssh2/libssh2/cmake/CopyRuntimeDependencies.cmake": "5a146613512f467192e7917561b305e31d52a85b3f216d5e3c6ca6d2261e9b03", + "components/ch405labs_esp_libssh2/libssh2/cmake/FindLibgcrypt.cmake": "af65a3a8ea63eb935b1602b2b75c7c993558f9118e8c12cf9f2d4614977d8c53", + "components/ch405labs_esp_libssh2/libssh2/cmake/FindmbedTLS.cmake": "db4ad3046a838c325ff39f3f083a2de39c3bcde4c69670610ce27b23c758c50d", + "components/ch405labs_esp_libssh2/libssh2/cmake/SocketLibraries.cmake": "857615772ee6a1b79826eb18889def1a626296262db78def698286930e3c6cbf", + "components/ch405labs_esp_libssh2/libssh2/cmake/Toolchain-Linux-32.cmake": "fc7c2718c2e628fe28db38406fb57e9380d202dce8b4d615ef8b818984c37a32", + "components/ch405labs_esp_libssh2/libssh2/cmake/max_warnings.cmake": "1a14b62c40d327d69ad1531e3372523310e642779da33c3865e6fc67df46835b", + "components/ch405labs_esp_libssh2/libssh2/config.rpath": "aa48652ef1709d015f0e627eb5d18d1c198d81c29d5f89a81362512fcba72b01", + "components/ch405labs_esp_libssh2/libssh2/configure.ac": "37d7a8fe37f7c5a7329f289030d2dc0571aa759d285ddab0a5b16ca27b1462b4", + "components/ch405labs_esp_libssh2/libssh2/docs/.gitignore": "b523bfc0065b99350f41f5f745f0be7698b3f5be00251e6c1016a5b620edcc7c", + "components/ch405labs_esp_libssh2/libssh2/docs/AUTHORS": "12228e95c6b41c76d00b6ca8f2bf7bfb3372f3f32b6c62f34882530b9406f26d", + "components/ch405labs_esp_libssh2/libssh2/docs/BINDINGS": "c711b535a9462815d564995eb84b997261fb9a2db4ef82a8c9b3f926dd7498b2", + "components/ch405labs_esp_libssh2/libssh2/docs/CMakeLists.txt": "713fa1933cf53a12a7ccafea3e8d9187c35967159e7e460a775e91e8a7df2464", + "components/ch405labs_esp_libssh2/libssh2/docs/HACKING": "5d2563866dc4fcc8a4ab352676e3d64b918b75e0a73ce7776b9eef7e8949d3b0", + "components/ch405labs_esp_libssh2/libssh2/docs/HACKING-CRYPTO": "ce85a00c816a80b24fa998598bfecb58ed9ea389a368c15eacf2e27d56f1be25", + "components/ch405labs_esp_libssh2/libssh2/docs/INSTALL_AUTOTOOLS": "6ca4765ca5ca117514e41067ce05cc24504aa29eab9a76bb9cc1ecc87c3280b1", + "components/ch405labs_esp_libssh2/libssh2/docs/INSTALL_CMAKE.md": "266b25dbe613f02e4662467c23ad80bb42a35ef9d579933ddb2d7b1d038089d0", + "components/ch405labs_esp_libssh2/libssh2/docs/Makefile.am": "5e734a3e68bf57a13404770ace3e4595e0a6c215526d2942a5fba3ebf3109828", + "components/ch405labs_esp_libssh2/libssh2/docs/SECURITY.md": "4314c11322a9970bed60130a2e11a0eb79c9de719a7c7c2cb227356d9771ba2f", + "components/ch405labs_esp_libssh2/libssh2/docs/TODO": "e3a304f76129bdb90371439567dffe2a8841e3a5c326f71000490a11241bc9b0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_connect.3": "5fe15d3e781382a8e935048dd266a89e9c3b63800d4714ceec6c78c512e49f20", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_disconnect.3": "e2d1a3af99d888e310c6e22227e11b0a42f1d265451a9e13ac787fe0b8075426", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_free.3": "332b5fb986c013ba363bd18d5e39c01a047d79fb22acf673291f1e19b4d8292a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_get_identity.3": "acdccde633dda1740ba043fb3f2b3aed884923c74ff3e2ad2f01d5a6b87955f1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_get_identity_path.3": "148b43bc669d3300b3fbf09ae57050a15ce074c8730ecef78e97ee9309ea179f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_init.3": "09029ddc71d63085dd6ccf92062ce6e31f0d54a1eb40d06587713814ddb4ee5d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_list_identities.3": "a498d332ea55486eb1c234468a8cf3c1886eb6b98bdd527a1b44fd06683e7ea2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_set_identity_path.3": "b60fb7e972fc2b420ff0a7452ddbf12597dbc9cb075920da16ee9c0eef7f8425", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_userauth.3": "d2119c63fa5bd1a05385bd176a1c8d2ee0139aebec92addd1601edc948f17855", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_banner_set.3": "1bd7a8bd59cb74d90cfed26c41701788afe7c0a667f686c5154cd0615d586422", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_base64_decode.3": "c48f88f5a6405738bc146161bf442e02c02073e0b9957f5d4bc3bd425bee82e1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_close.3": "e348d7548693066f863dde9a6c7dd21bf394aca51c1cae1c4999309eedfb4451", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_direct_tcpip.3": "3a67560c5846880066344d5581840a26a8509854fcf20fda79f9b2156e58757d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_direct_tcpip_ex.3": "5a7665c77afd8aa509c03d5059ece42adb912979e0fab608034e4554e3106439", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_eof.3": "7ad4590d1dfccf35bd2f7393e0d14b4247c3108ee2f48685b505c0dd9516e011", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_exec.3": "e7f79363e4fa61ce0c00f59e4e97cbc3101f55e2025b1156551aaf50c8522b87", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_flush.3": "fcaf2b8577ae6b8196313977d0686175a807fcccd3f3fce433028384da0f7bdd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_flush_ex.3": "33fb6e5de6afa0836e6439ea4c552ff4101a6f48bb73242f4868b181d40bc28f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_flush_stderr.3": "4f590d465d647b416c583c2b16693a3364e84da2400dfe7f9ffe1928577ca3ae", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_accept.3": "4f0621fe2a6aef5fefd50197974beb6e6c89dc41841b1d6052f885a773557ed8", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_cancel.3": "230ff1688acf2f4a7ac5d687ca46bd39458192a0662b3b8fa6edd8217c25117f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_listen.3": "fac440afa8233b6d3982b349d56c177ba9fec09464f1c5a5bf40ce32d600197d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_listen_ex.3": "49c5374f3b5c56213fe9a43ef4592cd51097cd1c9017fcb3be97c94847e8efcf", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_free.3": "a7e649756ff4a20b0f5bb6bc9f4647ecaff885c8745e9c304cc697c2c677196b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_get_exit_signal.3": "89557c3203331e1d21773b557659a0f21e1ecbcee90c372de3b6e159c7b78a7d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_get_exit_status.3": "d374651f3f72f3f179c37b4a44b815a1bdd998f803a121fc8bc5544c397224c8", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_handle_extended_data.3": "c8ba2c032cd2cd8fc5877845df624712457dcf1c092975f3c713fe75794fd42b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_handle_extended_data2.3": "17269accf920a28af6bd14770f94067083e2dfa56df4e08663844d0cebb78052", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_ignore_extended_data.3": "c00c30e1aa01c699c92c30c98e9ab8e543cb2fb23376b650627c56ecc3a1f275", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_open_ex.3": "a4153c3de3d2cb9a2faaa39eeb9b638c829db2cf4aa4a0e0a2cbd51098626e79", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_open_session.3": "63ee8e3220149933ebf5219335cf5b9fb107e23808137f782e8846b191ecf629", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_process_startup.3": "1023352b8152e5a1a2ccf2bc899e9539fbecaa2dff69ebb68ada088da38fc6b9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_read.3": "1ddb492b078cab328e718563f2fc5dc3fd737078ba272d078f94e554e2938080", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_read_ex.3": "931e1fad6ff1d629ed2b523c75e645a16344be8afebc0e2f50144ac8394146e2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_read_stderr.3": "6b3a6db85f2fdb26a07b95d6046127f3d5c709e6ee4bd72d66b9109e10ca8e1b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_receive_window_adjust.3": "01a3e1d79fce062cba8fefee6b8fe7ca81a1ad7a3c8cccf12801d7f80fd6265a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_receive_window_adjust2.3": "451f2632b8c786a16e87940f2fcb978e9d88fee27cb997c192c9e671b72b27eb", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_auth_agent.3": "9217dcc14a2c6bee93f5754b2fed7827b3dbb8efc335d7fbf4908e8a531570b4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty.3": "f7b4d6780a1b6ed5518e425751f55d9930a5bfa8e92dc0458ccdb06d7786ecbe", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty_ex.3": "ab2af9c02a3d127ba99cf27f0496643eb30810edb38a94f7df488f41041ec105", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty_size.3": "5ae6ade5d71da8ce3a31fd804c32600f54a3385b07cb8ed6ac90157a9a1ada26", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty_size_ex.3": "4b296b3a64b71c1842c0f12c70fe866734bc18f51e3907acfa3f04c4a997bda3", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_send_eof.3": "a83be7ac2b428f6d41df423e38c52d01f86b9fcafde2010336c7a57323808b6c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_set_blocking.3": "767637f9629f9b7bbbe24c3f3e13be0a83174f1542a63fe7daba350beb369447", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_setenv.3": "fc8773714c44358cf215d80dfdfeea082cc84ae0f33575d17a7825ffb785b02d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_setenv_ex.3": "d4641d1a3054af1fb1aa4819de5ce002b434e56745118d843adc70d902505447", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_shell.3": "e2986078e39068dd61d6d3df0d9e54adb0a489e55ba8051ae6ce3ad5f3c2c191", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_subsystem.3": "16e48c8ad515baef23e1ea94895cf0d2c6d397c133adcbbd20300304b64cab4a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_wait_closed.3": "8f7ad8093832b4b343b04eefe492e94a18be6f496e2074037f93b99683296663", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_wait_eof.3": "a96b063c1d90129420db176063ea4cb66f1b913a2d2b5ada2f3364eeda2d6543", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_read.3": "085331a4fb18dd396b016629ad241a7bf03afe78b0a09fec701aa8be526fab2b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_read_ex.3": "9faf5e32cc4e1fe69fa2e57dc31cbdf3f0e7bfcea339f3b7196f535bbe6be2e2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_write.3": "6daa6fd8d4f74957c709695bd74a741e7808e057cda1a0954e76f92f793d61c4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_write_ex.3": "052d12745f7a8a634ba0b3b36cf0a592c2425caf0679aaaca4776b664bd2d5c0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_write.3": "30bfc0efb86bf513f721200a89c9139687d58483826924b9b401797de74b6387", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_write_ex.3": "da8e46fcba16a2bca466d1397d8b06f03703c4cb7e7b799d582941e125c999b1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_write_stderr.3": "e15a48affe5a5044a2b70bf6fc1e3c6a1dc61c10c4440db4828080fe55e5a0f2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_x11_req.3": "e10544721e6dae96d4542abe07b43767ae6fff49a5bc87381aaf72be7d45f51c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_x11_req_ex.3": "ece17b293092b2319ea237a2855a4b9b7c89c6954ecfedbd837d3d02ce4d7a13", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_crypto_engine.3": "da0d23d0aaf5762db26587138ea9db2bd87eda7f00b326d459424f875bca01d6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_exit.3": "104af206d55e98ffa72ae0c5a505523220c8d6e1de27a37a5139093476d5ede5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_free.3": "8abbc67b852f9fabe09eb84540b610304d896721a04a4bee1e9d0e8f8f08c999", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_hostkey_hash.3": "82070c7634690b4bddc49f3c83b343c6f792c902e0e48247d055eaf3284f80e6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_init.3": "926b4044a52cf71dac8ac23cdf51d6e76bc92f5a3a72c65371549e18826c1cc7", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_keepalive_config.3": "7ebbb7cdc900d6d6188afc537c05c60a115030609d96571ac447ac396991adc0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_keepalive_send.3": "86ac214dd4c086239d59ac6582926f72544c788ad2fbf3ccc4e678b4109d32a4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_add.3": "29a052f853cd3f19efc12612d4e3224271bdc91b10cf6b73e866d7018d25f07b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_addc.3": "c5a2b8510dc1df43311f17073e7e720232f7a7e25d9ba7ae80efe2f26a133297", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_check.3": "2059d72130dc5b99c6faa8b399166a8495cf02b71313d6648778b11b0adab631", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_checkp.3": "88cac561cc381008f64d4c879bbe626afd669090648441c134cae83a5ea082a9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_del.3": "34fbfa29546d2bf0edc380270937658f818d2600e4bdc658d5ce28c7d255e1ef", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_free.3": "3e319da43cb185d73dc215a75351f330de2194608a1b12b8e0b623c900d4d96e", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_get.3": "fc04784b136786dafb210e018e758d5272c8d9d531c4fc5baac9f7b90f65bfd2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_init.3": "509721c49287e0232b3cfeb41a8d4b44a45a195222a5694baf9d728c77225abc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_readfile.3": "6d72d5be2d5dd56b125c1107632c58d5e8a692871182f3f883f5662f39d7dfff", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_readline.3": "e259eaedbe587c06a74ada7c1cf5bf28a168edfff2a60919985aa6c7a15e56f1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_writefile.3": "5ef6daaf96128c0b756c9faf38b5fd60697fa93504a5cb9ce7139a3dc14f7254", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_writeline.3": "32c23d5b4393297935c3fa6e03d57a3bc1d904e5e469cf775bb0516f9f885147", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_poll.3": "c4a377bc2be1c2789de7a57fa42baa51cfbb0bf4121153ee9cd5201507a8c2b0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_poll_channel_read.3": "5b3df35e57c3252fc63e819c69cc6405bdfd14c546b5cfc2a521563bcc9cb420", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_add.3": "2e7c2772fb78b750b5aa94c7bd38c100e52493f6fb050762af924e26ab2605dd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_add_ex.3": "76e23274e8b4756b03359b0fb5bcd05becba4cca1212ae2c164a32c2f10ee50f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_init.3": "5643aa57554f8daacbbff9e539c68cd1093172bd86d859109e6446ccc91a85d4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_list_fetch.3": "975705aa9fc187961fbab91751a5f41412a30d73d65bfe54862285061afc6c29", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_list_free.3": "5eba2104f91fb101014441df437c695b9b0b1e106b6268d623f886de6c237503", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_remove.3": "69423e4d9d6b76388f6160eb473e82449700569d449911163609c8b1c629ed43", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_remove_ex.3": "5c1632ac1685361577a4ddfd1f6257ecfc012225e1e8c2b126f93add0b5b6190", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_shutdown.3": "b152e6c493896da374b7b93468b23d7012e6232db06c331c158f9057b8053994", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_recv.3": "e3af95d4147fb29a893ee80c8af430b7df1d77048d814c5005243c02fe221e18", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_recv2.3": "9fc689585ec209d13e5a7c5db6750e07b171103bd29d3522424f6d812473b95e", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_send.3": "0b72a5932217f8e561840de2ce3e5077bb40e7631b1dfb6f439d4a2413f83cfd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_send64.3": "3225083c74987af71d4a2947a7852ac810fd87ab12532492f286d7e7d7547456", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_send_ex.3": "07818e45119b15208123655f945e1927c0971d21ae6d410fd26944b86cd41745", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_abstract.3": "56b29e317d2676d842f3854d8ffd89723a40992897b962d9ae07b56b2373a727", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_banner_get.3": "78804fe78c70c1fcc408a493564c989f3d3da36bf56d14344df150bfc65570c5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_banner_set.3": "c058557ca5d9633b560e05492212b52ee3f6477dae79f75c8ab4996828d88f09", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_block_directions.3": "0006e5c9788d8b2c3976274b715ab712fedb6ee4d3caa09071b62b846b7d44ed", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_callback_set.3": "6c33ad4047e740e5d020ba14cc5ce06beb0bf02b4b2f88c1ab7fd79e6e5f1b8b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_disconnect.3": "382845fee521c18828a9611c286919218fe51a4a3185f37f5c6e8a10a081db66", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_disconnect_ex.3": "5ed79115477f25aa8cf5998bf46eadc2383fd6e4eacee32622d961d4080ffa11", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_flag.3": "18317502888f1b7da8ef132500e009c8eed72cec5ddffbeda575a4c5093d8b74", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_free.3": "7fd404b4fb4c5e955cb2b8fee9b72a89864351e63c553e56a80dfc2af8bf200b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_get_blocking.3": "947a5fe43a518c13ba5049d820084ec6eede2bc3687923e67b28a75297431378", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_get_timeout.3": "4e808b2407358466171f2546c5220def1db4460a16d1f24c60a4a5186d6c0606", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_handshake.3": "fcb9fc145dc6f3b29871dcbe9c3d27529790e1cd3e20643c8aacb3d3d628fb5b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_hostkey.3": "0df40e6f599dacefcebf30b19331e4ce0abfad5bce75f5cffc8f4b7947bca5c6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_init.3": "ce1a0e9ecc5a17d607437b01f4ee94d5a0d8c5dbc8a04f1e26d3b74daedae57a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_init_ex.3": "2c169699aedd0f9ca16fb71a90618738dcdfa5b2b70d857a39c60896ba62b86b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_last_errno.3": "fe92e9c94ecb5fa33bbf51f866bb62bc4a1e5c3ea153dbaf34aa6553cd477ebf", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_last_error.3": "b14e30dc25d7daaf46ef119176af947efabfad29eff7f726635f2adb6260e97a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_method_pref.3": "6946c31e6d51b612852bed10d4ea869093a048f6d41131addbcb9c4dbbd767e5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_methods.3": "d8c8dccb3183da86943815b18ce7c903e07b02714d6ed8c27dfb782f852de8df", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_set_blocking.3": "33c01981b30ead73c614fcb6f7f224a39d6e849e6a9bccc9b8dd463719e1a39d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_set_last_error.3": "147c7ad527163e73f3fe285d16c980de60bba09813535a7623a1e0a037cfd1cd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_set_timeout.3": "eae71fab2f62942d4e5b66d93a7f49347a08ad1afdfc9a81ce8fcc0d0a9b0068", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_startup.3": "425118593ad0eaf0688c686d9b75f12b7cdb23d330445077907c6e2023cfef77", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_supported_algs.3": "a2fe37982e0f274bcaeea77ad33ca8fa06ea9377aa4e8196c3a8a827e2906b74", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_close.3": "95f03395996cb7b2652cab241a7d91d0c57bec6d4d8f8097b2932acb56eb7bff", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_close_handle.3": "c813fa985be5105cc3cacaf23dc01f0442628c005e629115992a280597301368", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_closedir.3": "1230d8cc661c016991f32b757b11ee6ddd1ac551e5522c5e009f21ef624dfdc4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fsetstat.3": "a7ab72ebfca8d295a2b48f2c14d831568042ef6a0528e590faa99f5e2dd00675", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fstat.3": "e354ea4b96d512a34db42be2eaaa2c7fb0bfed554e726aa79db7f45ade1f9dd1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fstat_ex.3": "2446ac64b425dbaf115b37d29107b66fc0291c2ebd17898669c406a4fd57b78b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fstatvfs.3": "a10a9bf1dda75b0e97966ed003d183728a8ded895eece58e458980bc742f7a39", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fsync.3": "bee468765b5d4a09a3b473eba0cf436328f29806953bc1f998d8bc97d2a3049f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_get_channel.3": "90e527f9eb6b0d17760328f6e3842f74d1d173fe88a7c9ec2357ca471e9c0f41", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_init.3": "585d782936f71157d141474c94c897d7ea292580445550c25c8fd44f5e03052f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_last_error.3": "8e7b2fa2c5fe4792a39a5c1c24baf041c970e3021511b36e59979ed64a18b4c7", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_lstat.3": "a01353b26374401029f5094a24beca08988ea201ca2197fef2b14f30bb2658e5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_mkdir.3": "14e04b070a6c351e2af6bd68f73a408e2982e9a358d5d2af5a46d8b422d27ce3", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_mkdir_ex.3": "44c17758d2b0336f94c4004bdd2debf9e1632ba12c6db6df495c09a71a58e59f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_open.3": "af9a8c90999412d3371218f59859ff91c6a83eabee75f1712adf94c5bceaf1d6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_open_ex.3": "11661fbcec142d9afee722f5ce779bd32f6e0a2b2dc45558c3bd47292105231d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_opendir.3": "62639f60918835e08f3c00d708cb32af319b9a56d3c2cb33ad409b60b347b31d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_read.3": "1d0435c740470b8a6a427da4331b576833eead72f9d976001d8a1f55fcf24815", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_readdir.3": "0e98293f67ae019adf8c5e17fa9f31f3e34b082c55ccd2119ee424f30c337fc7", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_readdir_ex.3": "7f9a2bda1d49d12040796015a842b592decfb076230ee9c8260c31e7b12dd2cc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_readlink.3": "1834815d254c351664cacf38c06a4b232f099787cc09a41ef719a1ff242e4064", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_realpath.3": "6b8e75bf89724998c414487d93f8c4899a3b1f4deba50806a798fdf9f9405bab", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rename.3": "eb87a9b1c94f38913c0cb62a3a474fe8c8f3cb0a874c61ced396a2d8bb92e510", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rename_ex.3": "12d2e70027755937df6de8b0836f75509f4fc5f1a5428fe5a92ae3eb23ff4b54", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rewind.3": "4caf86de2f35e2925ee637a68f7cfc2e76dab54571ada06495a0574e549c6a7c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rmdir.3": "86a1935b7bb291041eaa7c0788f417c6398b39fd208b6bb478329299ae72a49f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rmdir_ex.3": "17029aa15ef3e1c862731a7ee52e8f730dc8951e62e1c0539b922dbcd66810b0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_seek.3": "546a134db735df610032fa982d3c8c1013ced779e21faeff261d71041bcde8bc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_seek64.3": "07df7a2c8c9d75b198fa60909baa31e1c883002337a4c6b7a1b3a9c6ceb3a594", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_setstat.3": "39c7f5d489ea5ceb51bd9c7de237464f5c510f3ce0983e57f7b69207ef957e01", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_shutdown.3": "48bf057f1836924e3e5009890cb6e63ec9d11d0aa19abc258c75ee7c7bd097b9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_stat.3": "7fa4495645b580c216ca2279168b6b2f7c9c73a973dabf1997c02a0409d8c042", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_stat_ex.3": "fd19ff075f44a1713d765330d069fd63cffd8b2dbc09ce9170d926f25d5f70c3", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_statvfs.3": "5762f9ff7d56f44164db57fd048daa60173794c4e7a58ab2fb255e29f0ca2bb8", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_symlink.3": "ae7ea167057c307552405124ad54ee488db7354e7caa974334e88f5b2104c88a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_symlink_ex.3": "7e22a39bb97548428cddc8a9cf3bc7a1ff57cde878b337a7e177730bf5c51d01", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_tell.3": "ce22525601570f33d91469170d43470a8a9decf0b35ae82c2cea72fff1dc8d8f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_tell64.3": "db5faf0fd28de4738e3062555c1d6981c2b272d7b89bd85e3e83d2a03237472f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_unlink.3": "d8c4c60c41e81149fe14a4a00cc114d3f7bb4799ceea4895c67d79363da3ae7c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_unlink_ex.3": "64b0723444b716d2b809a3b481024523fc8c62ab45d3ec4274040abf824cf611", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_write.3": "a4706e9d6dabcde2aeccba27f7d7d5a3cef33dd21f4bf66bf5b181c3e8a3f9ef", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sign_sk.3": "7d35515c97ed9fcb5c6a43da9f3fc4feb1c5fabd64cceeca0a790bd0df955b28", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_trace.3": "636417e1798bce85c2058cad56493919c608d426acaac409ec1a489bdef90fe2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_trace_sethandler.3": "b37355eff49dacc9916818db61258f21665fb68993e57ca9040db056453bf8bd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_authenticated.3": "81115e3ac2549eadafc5ab8c73462d1c5565593106c4d995a920f718e5dd451e", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_banner.3": "1a7248076b5f48794ff638a3f44e88e297548d8e664b792fd6ec3ff9c5017c09", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_hostbased_fromfile.3": "265670d504f8db399e9253af673264b92ae8cc3593912e9b2e6aee436d02fdfe", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_hostbased_fromfile_ex.3": "a71631a3eb07ac88ee21beeabaf6aaccb7e93378c98eed228fa27f1575b04a64", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_keyboard_interactive.3": "17d55c3ba83fc9b7a2fa1dbf0e0d1886deb87616298b6bf424b5ac7d63d0da39", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_keyboard_interactive_ex.3": "09774448b68977b58a745775d5f568077960a9da178f5a2e570359e16b327354", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_list.3": "af6928a269c96480a6ea3a3452af7029577f69485fee36ecdd9dde48b4956a5d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_password.3": "4c8103bb95903b0b2ee6c2b1d0b3eac150ab31314ec023424ab564d29b1678a9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_password_ex.3": "0834a29c814a2d617369a2463429ec244fd116bce0abe8f1b6e61aaef35db3eb", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey.3": "874ece028410feb1bb33d481ab2789e6fadc9a9974cf4e0a72517b4c3fb81861", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_fromfile.3": "6864fc6411955179866986cf95f75ff41a022a4b60ceb177cf503da45a67b88d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_fromfile_ex.3": "060d36d8a06538035e0d7c678f78db16d68ad6f930c958ef3c1bd46f96f9ed39", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_frommemory.3": "5022660ab3c6c7f596b92e887debb3c580dc21f64be71b76c83c033c0fe36ef9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_sk.3": "5c779cca1464db0aebd956fc3fce989c0637e6e91dce4114991b457e2cb616dc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_version.3": "d3feeb9f870be0dacc7616c44dffae9abddcd22eec9cc8c18a0526af723ffce8", + "components/ch405labs_esp_libssh2/libssh2/docs/template.3": "740b501cbdd74773bdb93c8a4d1ae1e175f3593c0eb93844ea2cad0c61e14463", + "components/ch405labs_esp_libssh2/libssh2/example/.gitignore": "519ee26ed4fcf44a7ba26c65a50f13b343da0a0da55f14f94889b902a3a61939", + "components/ch405labs_esp_libssh2/libssh2/example/CMakeLists.txt": "f8cc011f16f189f485ed9060d71de862616c254dcfc1fafe49ff6425a4d89757", + "components/ch405labs_esp_libssh2/libssh2/example/Makefile.am": "0e7c6f2ea9a65a6eb253d721cabc8df573cd4d2606ddc7bd7499b701380157a6", + "components/ch405labs_esp_libssh2/libssh2/example/direct_tcpip.c": "1a335122f9e28b3883587768e8332f3883b462def477f8651b83fc1392e96dca", + "components/ch405labs_esp_libssh2/libssh2/example/libssh2_config_cmake.h.in": "115c1b79ea918a83de959f0f50eb98c2ce252b21b566b9ad56f3c23b68e48ae7", + "components/ch405labs_esp_libssh2/libssh2/example/scp.c": "87736832ddc36e80b52ed6b7f1c87eedcb57d739c80dcff5bbf2d610bfc7f7c4", + "components/ch405labs_esp_libssh2/libssh2/example/scp_nonblock.c": "dfa78c57e18acdb437f3a643dbace70802aa7d2d504adcd47ed63f744189e822", + "components/ch405labs_esp_libssh2/libssh2/example/scp_write.c": "3a3c4dfb3c4688558716a364cf0f4d8b767bf30c59cc6b352394a2d698370930", + "components/ch405labs_esp_libssh2/libssh2/example/scp_write_nonblock.c": "8071bf056b72eee39bbb1ee173193a79e6ac8a2812724b3e31bb919c6b8ba370", + "components/ch405labs_esp_libssh2/libssh2/example/sftp.c": "6a0bcb5ec7b3066cd040bfc29243fcb36f8375575db17415974a20c29892f6b8", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_RW_nonblock.c": "a2eac2e5433d8e63fd416dd8d0b1424536b4dae701360bf9ec3024495d8c6eb9", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_append.c": "e9aa3ad34d7c9aa119a841e16e99657aa28596b184ff38d09df3a1319dfbf9bd", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_mkdir.c": "51f94316a6fc8ce1c6de9bff0599fa95a950a1424e94b676410d76b1e1edc879", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_mkdir_nonblock.c": "0fb08ab3d217af555d7512693a56c63094642247054def280cbcb08e2a3612c4", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_nonblock.c": "c7236ccc7897e1abd3d9176a33cbd059327d30fc95c7803f7e5f99bf3c448a3f", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_write.c": "7e972aa778422c962ba0ebd2fbae109865b334e33c371ae94a8634e74ffd5473", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_write_nonblock.c": "6b18c9371c2ed1e22b005232f80b99959cc68f2e0dc1351fa73d678e7c64a329", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_write_sliding.c": "b88419136786cd31709d9466b0e4a131b990bbd425096276e5699559863d4bd7", + "components/ch405labs_esp_libssh2/libssh2/example/sftpdir.c": "d186de774a29db36a87fe2f66011acb5c5847316791c98f39dc2749a4c448209", + "components/ch405labs_esp_libssh2/libssh2/example/sftpdir_nonblock.c": "6282ae10e701e48063a793ab2e7a819be77f7267dd7ec29264339c41c5dad8ab", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2.c": "2789139110316e87a06b4d6132fb86081c545084358a3ddf6bb5128423eaed49", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_agent.c": "3184d5a396a9067279ec16070c699a8baffdc02c70930f8cbecbd1cbbd489d84", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_agent_forwarding.c": "2db3d78ce1c5bdb2453f7d22cdff09cf1dc3e40aceb8a54faffe6f76af88d1c3", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_echo.c": "91c519486541145f579c550fddb5ffde5933ba0aaf22366ee8aec50c0cfe4933", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_exec.c": "67afd0ef23627c87eef2e4424967eef26f8154ce50c357cad85f7d3764fcd5b9", + "components/ch405labs_esp_libssh2/libssh2/example/subsystem_netconf.c": "9b076de4366e11ca81e88d60f6dc41ff3ad897d3096f148ce4ce00102d7256b0", + "components/ch405labs_esp_libssh2/libssh2/example/tcpip-forward.c": "0a929eec2a7274e7592ded5f63230de45c1f30578ce92ea14a010a33b231ac42", + "components/ch405labs_esp_libssh2/libssh2/example/x11.c": "310b0aef741a513db213a895fbf772076e35c2ee83eb4ad1f300493ef6b5b436", + "components/ch405labs_esp_libssh2/libssh2/get_ver.awk": "ac9314659d618e57f0d57e9cb2dc5ab14ca342f099de6738e93d58b91f698f14", + "components/ch405labs_esp_libssh2/libssh2/git2news.pl": "26cad7a3870941f21348bfdffd05fff7a1e1c650b8e38fe469bab3a2a221f26c", + "components/ch405labs_esp_libssh2/libssh2/include/libssh2.h": "2d36bee9e1f99a333cd21c489f649f574fb1c615165da1cd2fa50f5186315f64", + "components/ch405labs_esp_libssh2/libssh2/include/libssh2_publickey.h": "2d419bdfbc155cec62cc23d7cb87f3d9361c4f26ce3b3910c74cef715bd2e70b", + "components/ch405labs_esp_libssh2/libssh2/include/libssh2_sftp.h": "8a0c63c323edc42286cc608f9a53cebe46ac91432e1080a8520ab69d3caeadbf", + "components/ch405labs_esp_libssh2/libssh2/libssh2-style.el": "14bd86ae83b499f88b47f57cee18f1a7f4f41650e16e34af4b8ff03970c3c059", + "components/ch405labs_esp_libssh2/libssh2/libssh2.pc.in": "a2c375f048235970c995e4a091fca2cb500574151c356f7682d44deeb90623a0", + "components/ch405labs_esp_libssh2/libssh2/m4/.gitignore": "b96df5710e539dde8424e3c38174598386aeaff62e4b4a3a878a3f8290a7f9fe", + "components/ch405labs_esp_libssh2/libssh2/m4/autobuild.m4": "37dfd034b5ea52bede69c54901b818a461ae73e2ab1e28c61c229a87f24a1817", + "components/ch405labs_esp_libssh2/libssh2/m4/lib-ld.m4": "18c4c458009da32c9daf0ea332a539e5edc82ba009b6c2faac004626313f00e5", + "components/ch405labs_esp_libssh2/libssh2/m4/lib-link.m4": "d7aab3772e5b60d3ec57ae8dc66d9b762f5c68ef1e8516df25fadfa8bdfef379", + "components/ch405labs_esp_libssh2/libssh2/m4/lib-prefix.m4": "4797426d11dad1e5e4fdbc8bcbc8b10d9750f47bcb74e4c07a953a15265e902c", + "components/ch405labs_esp_libssh2/libssh2/maketgz": "a4ef1a17c664f3bf350ca4357219a6df4af7d0b27c4588fccf5f1e630f54d2dc", + "components/ch405labs_esp_libssh2/libssh2/nw/GNUmakefile": "d6afc1888b0fdfcb50b29a3d7080a4183de41a444c7063db93a1b56d533d8dd8", + "components/ch405labs_esp_libssh2/libssh2/nw/keepscreen.c": "f95e6f4851f16bde13e51a1f4f6f405a142c6a7940beda74de8058db2f170ef6", + "components/ch405labs_esp_libssh2/libssh2/nw/nwlib.c": "d81b0ad6d05938507ebc3c0510021e889a2d68a74d50709df981d2339798eb78", + "components/ch405labs_esp_libssh2/libssh2/nw/test/GNUmakefile": "fb00a4a6776f14c1789ac8abc0b0136b79813177221355fbd3c5b1907da938e2", + "components/ch405labs_esp_libssh2/libssh2/os400/README400": "f5ce6d4f86e2334f5c271020195fb0964083e19e2f44dea4c4d62e7a9bc9f4da", + "components/ch405labs_esp_libssh2/libssh2/os400/ccsid.c": "07d12155f5b9b2be9e5477fc2818a7e98183eedc247370de04d718eef506fdb8", + "components/ch405labs_esp_libssh2/libssh2/os400/include/alloca.h": "f2b4c60ed1f78832b9141cb64e5d1d8e187d90afcb5f9f1d56dcf3f9e185d236", + "components/ch405labs_esp_libssh2/libssh2/os400/include/stdio.h": "ce35104d75377458c0c38aded5375141abf22e71215ef7533a482ceec279c731", + "components/ch405labs_esp_libssh2/libssh2/os400/include/sys/socket.h": "05599c77ea5f79337a77e7b24f4d63f40b929884141fbb66f356d825c09c8dfb", + "components/ch405labs_esp_libssh2/libssh2/os400/initscript.sh": "b27631198e5eea8048684f8fae95ef27eef1f712742265022bf4eb1ebfe589cd", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2_ccsid.h": "13a0b3c9165d7ef27ce242c64ae191f876a1fdd65f0b4d768cc3235c2509910d", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2_config.h": "313f35a0e84d1474dbdb3173585e53c417956a8f92365a75d5ae53faf179345e", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2.rpgle.in": "0ce3e5bb7c33bb6dcf960af6267b4c0e3cc16259ae881724624c9fafbcc090e6", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2_ccsid.rpgle.in": "439d9e4c68c9b20a618e305e51f54f817a9cc51dd37b62f5792232048ed3ff80", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2_publickey.rpgle": "b138035c36feb1816c6a99b1d98daff7997b05d02325cad1d9909f983e4a330e", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2_sftp.rpgle": "7d6fcfc290b07c8bafbbdfcf61e19456ab6961afe23a0aa142110052a33e7ace", + "components/ch405labs_esp_libssh2/libssh2/os400/macros.h": "38360f3613c00f49178996cf53d2519009a0b3fab161db7aebff143149730c5a", + "components/ch405labs_esp_libssh2/libssh2/os400/make-include.sh": "c75efa9eba5bcaa1e75f60110dd463c2c6866b486186db705d49518c1b0fd8cf", + "components/ch405labs_esp_libssh2/libssh2/os400/make-rpg.sh": "41cce97d1dec97571160c98967db4ab27af9c7890cf4f7aa238b3d6b6aa69eee", + "components/ch405labs_esp_libssh2/libssh2/os400/make-src.sh": "c750bd85a5153b10c61c069a7d1ec253ec3587554f2da60a144dc4246ff50e67", + "components/ch405labs_esp_libssh2/libssh2/os400/make.sh": "07f221c0d6a9e7b1c55e5d1cc8e3babe7edb6b4bad3063827b55265bec9456e4", + "components/ch405labs_esp_libssh2/libssh2/os400/os400sys.c": "2c9bc9de576376b0a37c401c64b59990e2f74ceafdb0a8c6555fb8de5be2b01a", + "components/ch405labs_esp_libssh2/libssh2/src/.gitignore": "b9193860f4137ca619b15f6f76ecbbf8df6210fc9a5ef2d53c856279e2b848fd", + "components/ch405labs_esp_libssh2/libssh2/src/CMakeLists.txt": "00462a0ce4e94446ee6c32616518db7f0539b90980d4d4a2929c295ff9dc8ece", + "components/ch405labs_esp_libssh2/libssh2/src/Makefile.am": "655563161c47286f17fd9d992f15115630e3910828e838f11759bd70bdc91357", + "components/ch405labs_esp_libssh2/libssh2/src/NMakefile": "bad4819608f02f282aae84462a7c3f1d1b199ee0fc86abdc9ab7326ee6482576", + "components/ch405labs_esp_libssh2/libssh2/src/agent.c": "29c2a52cba4eeac57ed9a3808cdefbc4e9e07f269152dddcc7038896eacce424", + "components/ch405labs_esp_libssh2/libssh2/src/agent.h": "1348e28650ce7f4350e4e1b92e26d7c45e729fe3b9cd68db716e40a64ea15269", + "components/ch405labs_esp_libssh2/libssh2/src/agent_win.c": "1c8d67a82e21c539c62f3a0b4c715fba81ca40cee588588d5e4f1abb389966b1", + "components/ch405labs_esp_libssh2/libssh2/src/bcrypt_pbkdf.c": "604344b6447e2da31608c00e432b3cb62cdbf11f25c6ba3c64f539a9f771436c", + "components/ch405labs_esp_libssh2/libssh2/src/blf.h": "b54edc453639a810289315bc3d4de37bc67bd0537260e1df7f8f21f5f1c36c6b", + "components/ch405labs_esp_libssh2/libssh2/src/blowfish.c": "23d5952bb059823ad3a3174d641655135991a9e849fadd00634516b977cbc17a", + "components/ch405labs_esp_libssh2/libssh2/src/channel.c": "0d23d9583e2f14c8f660d614ce16e8f48a41421434db588f19a953ad100ac3dc", + "components/ch405labs_esp_libssh2/libssh2/src/channel.h": "3be8e8b444461111fe0d35b21137ffcd4f681c1357616e0db4908bd434e97bbc", + "components/ch405labs_esp_libssh2/libssh2/src/comp.c": "0fd0cfb6b74e2d94a2da15b27e8e99e42f277dd12fd27ccf17bf566ad8009993", + "components/ch405labs_esp_libssh2/libssh2/src/comp.h": "7aa028c23316132522362bc9f397e22bae94e9e620eb80ac12a2009278532926", + "components/ch405labs_esp_libssh2/libssh2/src/crypt.c": "04e3683e3a16046aa7736b2401bdebea1feffc1e7fb928952dbd53adcc5a493e", + "components/ch405labs_esp_libssh2/libssh2/src/crypto.h": "9f53448f79e67731c2819b04e911228d47cb6792fe82ee818816f795cb40ffdf", + "components/ch405labs_esp_libssh2/libssh2/src/global.c": "9551963ca2fb9c321703db04952d9b05e2e6049e12d8bf6ba6e9291920b87a37", + "components/ch405labs_esp_libssh2/libssh2/src/hostkey.c": "563747e8648e09002894c1d2c93544013b17bfb3468c3e04a010306254aa865b", + "components/ch405labs_esp_libssh2/libssh2/src/keepalive.c": "acc373252f0624126226e2528897757da61c870374d5905df29a17fa185214ef", + "components/ch405labs_esp_libssh2/libssh2/src/kex.c": "f71ab4c2ba89fc4bbb560faaf955227297ece57378a984a7c67b41ef867aec1e", + "components/ch405labs_esp_libssh2/libssh2/src/knownhost.c": "2ef607c0bb2ef7ec9a4cf41158813ca8c62c55ace046a02a2b862cfdede25e75", + "components/ch405labs_esp_libssh2/libssh2/src/libgcrypt.c": "209ed04c45e4f9eeb903083853c23708d5748bcf77125664d613ffefdc2219dd", + "components/ch405labs_esp_libssh2/libssh2/src/libgcrypt.h": "7414cd0c7075c66402bed0c09fa082b40a264e50b443bc4d2d1f79991d8e5f8f", + "components/ch405labs_esp_libssh2/libssh2/src/libssh2.pc.in": "46db28ee6987b9f399c0e3b02dd5374fef2831fd4051109a478e85832e1913df", + "components/ch405labs_esp_libssh2/libssh2/src/libssh2_config_cmake.h.in": "07fe4470fd1643c51e5f2a868b053d733aaee891f1f886f4b8b848fb70db76cb", + "components/ch405labs_esp_libssh2/libssh2/src/libssh2_priv.h": "ea15b0d55cc80ff943c381e5c4758b1d6be9653b797a520ba50b8b85c5ce1818", + "components/ch405labs_esp_libssh2/libssh2/src/mac.c": "3ff6c3d22e5e9a0cc2d69b2f840606f560b83b9d40e276927d0854c20ec35b27", + "components/ch405labs_esp_libssh2/libssh2/src/mac.h": "ead9c368cf6700776d6083363a275e26d0e89de665b40b48fed1f5cd6d783b3b", + "components/ch405labs_esp_libssh2/libssh2/src/mbedtls.c": "0198525ff6b9255a7e3ab058d687fc041b3e704d1cb22584d32d6e8e57f3f133", + "components/ch405labs_esp_libssh2/libssh2/src/mbedtls.h": "c053528583d0eb839746addf0d399f86d20dfdcdac05ef977ec622f418e1177b", + "components/ch405labs_esp_libssh2/libssh2/src/misc.c": "6963f62e19e09399f871d7d3f87b16b8ea3810c8e5c38c3794b1c69efd3c1603", + "components/ch405labs_esp_libssh2/libssh2/src/misc.h": "ced7fa5c4d17e22c4f3f5407046ea0bb764ff11ca700257bfdc7728a0a89a9e9", + "components/ch405labs_esp_libssh2/libssh2/src/openssl.c": "88fa09c6324935ecee4c42f59cf5b07d069c3cc8492ab312404660fc23a7bf81", + "components/ch405labs_esp_libssh2/libssh2/src/openssl.h": "5140dd590337240cab5d2b2a4f11bb6e80b451f4e18cac77c973995b71ae49c6", + "components/ch405labs_esp_libssh2/libssh2/src/os400qc3.c": "130c4c3d3d202c4c1576cfd4fff5744e41908432ac79d8481363efe110938301", + "components/ch405labs_esp_libssh2/libssh2/src/os400qc3.h": "0e9f256b38da841315e5d82939ee52c8c947b6d1efda65f44d26cf2cd74b8db6", + "components/ch405labs_esp_libssh2/libssh2/src/packet.c": "55a13ba8b444f8cd62a9f0da3f07f982f5faf46fbf6df3bb825df1472db4c870", + "components/ch405labs_esp_libssh2/libssh2/src/packet.h": "cbd3fe922ff28675f6f39b31131d7832a07263356d0e7d55197e40d5fe244577", + "components/ch405labs_esp_libssh2/libssh2/src/pem.c": "d1adf7211b744554b8c41180c87e8d0aca2a7babceee91c75032e68655e41e22", + "components/ch405labs_esp_libssh2/libssh2/src/publickey.c": "3e1579cdc688dee088294975ee4b09316cc68cd9083ea6170a8d4726d820ea6c", + "components/ch405labs_esp_libssh2/libssh2/src/scp.c": "ef7120de5d824d9d4135b846021af8f42c44ff790dacabc8c4d23bb702abd81c", + "components/ch405labs_esp_libssh2/libssh2/src/session.c": "359f57b322d50a97ac7732bc84f22d9be9e336017a2cc9d050b06779be701bff", + "components/ch405labs_esp_libssh2/libssh2/src/session.h": "c3918ff057ebdb51116d7552e27b9f7d18461e1fbba4c1b635465dff909d4623", + "components/ch405labs_esp_libssh2/libssh2/src/sftp.c": "10a9f0076259b593fe45e71bee3b7a28ddeadfe8077a77fbbff4701cba7533f7", + "components/ch405labs_esp_libssh2/libssh2/src/sftp.h": "3b4d6460b857e32707116814f1ddc10dbfa5f804e407883e77bdad6c36db8c14", + "components/ch405labs_esp_libssh2/libssh2/src/transport.c": "77251235630878e6221516c1205b32ba786f15bd4d9afead8156a471e4312b4a", + "components/ch405labs_esp_libssh2/libssh2/src/transport.h": "4a57bc5ecc21db41729319d8fd34808f042cfa7d155be306ec2165f2d81f010c", + "components/ch405labs_esp_libssh2/libssh2/src/userauth.c": "80114428918476778385aed818ab2686a4691cdabe3b029e6d57c27431b91b22", + "components/ch405labs_esp_libssh2/libssh2/src/userauth.h": "7d930eb690721808c6d89ba917045827118a3b98b04333935d8e91b49f651b84", + "components/ch405labs_esp_libssh2/libssh2/src/userauth_kbd_packet.c": "d809a66f078569a118a944d69222ddfb5afcf0b529b245bb70725f7973a440ea", + "components/ch405labs_esp_libssh2/libssh2/src/userauth_kbd_packet.h": "f86686c43cc9ba1d9f6c8b62d801f753f350c9a3ddad3df42014fee8a2dc5eea", + "components/ch405labs_esp_libssh2/libssh2/src/version.c": "d766fe3f653d73f5a20110e7424224e788f5a42a7deadfaa8391b5a3f0694b90", + "components/ch405labs_esp_libssh2/libssh2/src/wincng.c": "c5cd20cd35a939c0b58a3311e29a8b3ba45101467a9673e693f783a31e7a636d", + "components/ch405labs_esp_libssh2/libssh2/src/wincng.h": "b9895f00d224866aac9ea1cec71ea72a2592ecd9411028ad1220869c4647edfa", + "components/ch405labs_esp_libssh2/libssh2/tests/.gitignore": "a76314b370eee3d3c44c53f5c64c9687e898909dcd3acca35aa3d483abe26e0a", + "components/ch405labs_esp_libssh2/libssh2/tests/CMakeLists.txt": "eaed8e184360a676fc5de691646a4049f7072eba226a1cef50c11cba0b55a687", + "components/ch405labs_esp_libssh2/libssh2/tests/Makefile.am": "2cd881e6ed013014f37ce5c318f39461745514c109f17e58db6bf88376908542", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/host": "6eb0f1bb23d7877ddcd502159e6673c053b5ea1846630f21651ab58ea25d7a6f", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/host.pub": "0e2479a973fbaf1f7f5dfebb111e2b199ee59c0dcfdf646d26760eba0b8b2aa8", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/sshd_config": "2ad4ea47ddb633c7a2e000f2d6619d08bf643591f26a7a0b92d0befe518ee951", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/user": "776aebc0c12e466e4b65f1a44ae5235dd70687ab03f283aa3d9a6df70d3bdbbf", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/user.pub": "39bc4445c24c32fe5e64a6ee02025f3508b4334b2813e1a87c40d44ebc5f8c1d", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa": "2e5b8a618e853eff7b3e0d2928203529fe18a3ae62b46a82ccd48a750819b8c2", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa.pub": "12aecbb237794fc79d4a96cebad1c4badaa1902b3f1788cca83b28a1f977b895", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa_wrong": "21f66160d72789400c5420f460fb716cde82b5afc5c09f3f7512d310e3c8e0b2", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa_wrong.pub": "0274eed003e62413aa894abad044296c6fb3cc19450457a282674ed3836518ea", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ecdsa": "8fb4d570516afc175869de7686125a828e18c38ddd4c2524c5a8d05c95ba7e7d", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ecdsa.pub": "bc756bc47e3afd11437cd40ebe8ce5c8fca92ee03c6e3f01b6c5b44001bbc7c6", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519": "18e808415d2f344a20b7cefac12f0df0af4e404f446f5c690000c21987ce8795", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519.pub": "e52bcbcbdcdbf547a121e92bbb6f5342375719988e33ffe7f228dd2b935c98ba", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519_encrypted": "fd1e9378f94f2d5514e16f32fcf175e8303433750c81f2def3814d5bd44a13e3", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519_encrypted.pub": "7ceb4062d5fe17f190eb32c894e4cfd76e00db7c1b16de7516df8f910649469d", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa": "9d8f4c955624a4af6fcb754e74e2abe1d3e7fe6340f6063617cd58bf122a2d59", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa.pub": "4293f28b7033d459618b277374d7e932869964de131bba1d427030cb5e70c297", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_encrypted": "fc3872744c7bf6db2df4ab2ea5701370cd8bd39367d659eaeae49b2dbe7bca34", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_encrypted.pub": "1f340ccab8b86e51d4ee7585d61d5e49e3a32338ba9eeca65988a1d751112c5e", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_openssh": "a146196a5b2189b40bc00bdcd1958165106ca21e72a7d02c0a7f95a6dd926487", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_openssh.pub": "d564da6c612286603a83af006c3a6efe53885a2417aa25f234818612e16bea66", + "components/ch405labs_esp_libssh2/libssh2/tests/libssh2_config_cmake.h.in": "193a748944f6bccd3787b1c3958ddf95c1c7ad9b25e5b8f4b42cb48987e34668", + "components/ch405labs_esp_libssh2/libssh2/tests/mansyntax.sh": "71c56796eaa4008910b3d67b885b9a7e2c018d0f88be4bb290334afb9ff23bde", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_fixture.c": "60c179e44b04a81f1bbf09aed2cb0f0dc85345070fe83b97ddf8c29219fa5d68", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_fixture.h": "21935165166ce4518c6534070cc506fcd85ece95238fef29e6b0be784c05d7c0", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/Dockerfile": "bf498e530751418dcd88ba439ad3f84837a7fa2d0f6ed2d2f2351a1097c11550", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/authorized_keys": "58c4cf998535eb4123eddf7cae7da4413eed50e3827320187380ec7925fcf61e", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_ecdsa": "14e72246d3990d345c30cd3d06c5c7ba9496057d94da2f5a6f14a7c636663206", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_ecdsa.pub": "2925ca6bb4d280aec3dd68041efc2f06e959295932a26f73a263c939c03e3220", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_rsa": "7297a4c658d398564d75964e503da94e845a0d709f64b393e3017e66dee0fb4b", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_rsa.pub": "338886a78519130b9bac71b7e8f370256d5b3c9d249fbfd2d7da90dd1574411f", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ssh_host_ecdsa_key": "03753b2b4942081d1f33201a193487ebd5a577e0bfde45f7e03a1de5ae404688", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ssh_host_ed25519_key": "18e808415d2f344a20b7cefac12f0df0af4e404f446f5c690000c21987ce8795", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ssh_host_rsa_key": "11a57dc115ca17203d6382ad6fdcd8df33bd0f23ff6bf38ee4a697260ffd1a11", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/.gitignore": "b768be5cb4da9a7050fae93fe7b2c01073cfbc5ff40cf88ad63b6f58d0202292", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/Makefile.am": "049665a167b9f4cd664b12884ae4470c0b0b2077931a056ed55d61784b230d88", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/ossfuzz.sh": "6fde8ca30e3dfc0ade9da4d06f5e34f73a51c6fea72e3a1348cf5ced10b73d80", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/ssh2_client_fuzzer.cc": "cc7f1e67065aa6938b7e9bf8aa237d1414052c1b91ed222e2baa61e5def9bb69", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/standaloneengine.cc": "f6eb3ebf7e14252339a21fb887a08b2e7638a7ac77f706ed80508b2c0d54d81d", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/testinput.h": "ce435e13e87abeec0a297ef3b566268496ecbd517c1d09dfa2232dcbbec9be2c", + "components/ch405labs_esp_libssh2/libssh2/tests/runner.c": "696b83fd77bca60560c1609212c59ad986bf151cf72520b63d23643111a7ce4e", + "components/ch405labs_esp_libssh2/libssh2/tests/session_fixture.c": "975103411a50f033df3b97b9a50136b39185dcb521765f7a6cdc52d5438e4b55", + "components/ch405labs_esp_libssh2/libssh2/tests/session_fixture.h": "d4f098a586b5f7dd0f3785b86933c08096bc12a2e55f07fff470db6fc7bbd076", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_ecdsa": "796da5d8d420f644f47feffffb0357ac99b299471e4d757f21b6cc8bfefe8f0d", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_ecdsa-cert.pub": "0f2e6d1b46874a01cc36ed766533301622d64fa88988575ca77eee56da7b3952", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_ecdsa.pub": "d6b6f80d9117f896b99933eba19b012f55068ed8b77956f1a7b0510026c2876f", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_rsa": "934d51f8e803a1c10125653a14153e6838ee9081f87eb6dbbf87f8f214a43264", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_rsa-cert.pub": "29091d3911e30d80149525c8c288e66c5a8a99fdb3816249aad5c5886df0ce5c", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_rsa.pub": "4b742a4f19b1b468d939792135ce6a7b831dd0c8f737321c09a1281d7eb49427", + "components/ch405labs_esp_libssh2/libssh2/tests/simple.c": "4afdeef598aa669b5cd0e7388dcf2e579f2c0f9c954face71d366250101d270f", + "components/ch405labs_esp_libssh2/libssh2/tests/ssh2.c": "3a8605fd3dd6151c569bc12c07ecdc33de7d704b6224da2dedfe3c76494e015b", + "components/ch405labs_esp_libssh2/libssh2/tests/ssh2.sh": "7bbe65ee20f4e47e9264bd74700cca16ee066aba5fb9e4e42f46e1cfdae4930e", + "components/ch405labs_esp_libssh2/libssh2/tests/sshd_fixture.sh.in": "c8b93076f66222f73329472ec151b210e55b39024de5d3c18a4c609b65d13b7e", + "components/ch405labs_esp_libssh2/libssh2/tests/sshdwrap": "21649ba440cd534f4bfd52c0a8de339565768b373c172dca106cffcc8bd06e09", + "components/ch405labs_esp_libssh2/libssh2/tests/test_agent_forward_succeeds.c": "a5b9f9009c6818b86f235debc2ee15de5ceb0cfe1d9b539270167058afb4e6ac", + "components/ch405labs_esp_libssh2/libssh2/tests/test_hostkey.c": "f1059c3ac304332342f39f32288afa3f61f9bdbd5d617fe6052491b20bc0672b", + "components/ch405labs_esp_libssh2/libssh2/tests/test_hostkey_hash.c": "e745d8b4ad92c858dc588e3494e183f47d591c1ef2a13b63e2122f478545093a", + "components/ch405labs_esp_libssh2/libssh2/tests/test_keyboard_interactive_auth_fails_with_wrong_response.c": "32dfdccb447dfc0b17423cfbff8971771bf260fdb72e3c7e23ec6f62105c9fd2", + "components/ch405labs_esp_libssh2/libssh2/tests/test_keyboard_interactive_auth_info_request.c": "3e3bd0ab170d9d782a08540755030a4b1e1ad5129003381e0f19543b1005c438", + "components/ch405labs_esp_libssh2/libssh2/tests/test_keyboard_interactive_auth_succeeds_with_correct_response.c": "db57b8ed26a1314d5ef534036f383b12363d88ce54e0377086a298f276e9481c", + "components/ch405labs_esp_libssh2/libssh2/tests/test_password_auth_fails_with_wrong_password.c": "e3d588d9c6850ab69bd7674d2027563ff9f1491740637506d80875e66609974d", + "components/ch405labs_esp_libssh2/libssh2/tests/test_password_auth_fails_with_wrong_username.c": "c91608bdda3a83a62876725ae2d7002ccb3332bcbacfc9c9578e7488c0ed4cef", + "components/ch405labs_esp_libssh2/libssh2/tests/test_password_auth_succeeds_with_correct_credentials.c": "80d253225d68bcb7dc4b94b53374aa4de86c6995481de0974b6284bf87a91583", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_fails_with_wrong_key.c": "104b08aa9bb5f1006e07e59dece417a2d6a5f60ef6c3f8dc62b6a8af95d413e0", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_dsa_key.c": "4b397de742f0d2fb15e86d20451f109fedd1ba28b0622496a2d030f9e9f9ea5a", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_ecdsa_key.c": "53bd6d99a243aaedc20f7de5c974c7c04e38090a415d338cef2d7357d7644912", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_ed25519_key.c": "207f499812271669d2a9ff5a286761a45840de9230c07bf72426fcd59a682317", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_ed25519_key_from_mem.c": "4dd0a8251a41d0dd68490fb7abb9b0a1cc190af1603815f3050e29e2a7d6bc8a", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_encrypted_ed25519_key.c": "6e5c107ad53c144892c54459f89ef2cf8a25cbf977bbd978e4517cb5959a2565", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_encrypted_rsa_key.c": "dbc95a803a54364604ab379b512fc98c33d791a1df4e33e4027b881ecc2e75ed", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_rsa_key.c": "93cdd2513af42d46552baa273401910dedd014951f836175ec98b827532c5b6e", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_rsa_openssh_key.c": "4e6d3ace02cce1ba8c1b4b6e5d774a8a4d259eef8314fe6c3ae0d6003a87dcd8", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_signed_ecdsa_key.c": "f16a0dc74d16f0d27f10867f0ddd5b306fc4b16b2bd8e401a5451ce71c7649f5", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_signed_rsa_key.c": "e8744ea49f5e4be9798d7ea2a93fc05bd6d4519a4bbda40dd80c421a7cc33ce6", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_config.h": "1c5c4ba6ab33bd1d9e4ce0d84e1107ced89d27a80e8505e1b428fa942edefedc", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_example.dcl": "7726a5d4f07d522aa712da8a6ca7b998cd93ca950aaa544a5eed1790dc69c775", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_help.dcl": "9d04ddc32831abf63b7e042dd0677da83599f11497d364b02cbe780419e248e4", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_kit.dcl": "e7c23c9db4583f6944cd8973cd813a6d65749170417b8384f94db69597f81f1d", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_lib.dcl": "1549134cd4a4bdf2543f900ea9c811de1c67895e1e830f7ddfb384e7601f56a4", + "components/ch405labs_esp_libssh2/libssh2/vms/man2help.c": "ae61cab505a4a9c87bdd103506ba9a36fd7ba92714edd9f67d022d8a9474e6bc", + "components/ch405labs_esp_libssh2/libssh2/vms/readme.vms": "30b5d682da37cf16352152daa682cb04c56e1044c77fc4c4da77bdc9709c33b8", + "components/ch405labs_esp_libssh2/libssh2/win32/.gitignore": "06c9a331f6578cc30ba460b468e23c59fa31f5ef07c7525f5cf1c6b262d32d3e", + "components/ch405labs_esp_libssh2/libssh2/win32/GNUmakefile": "776238af38e7fb1ac52fe22c261f28e7127152184d7f561fc3ccdbc92e22b28a", + "components/ch405labs_esp_libssh2/libssh2/win32/Makefile.Watcom": "475b8b37143bad986386ca1d2c777e9f8e46d0172ca4e9f70c613c84bbdece4f", + "components/ch405labs_esp_libssh2/libssh2/win32/config.mk": "e2172a92c5b5b9f2215c5c11128009cb6ba8a1f25402990c1f7e8ae78449d289", + "components/ch405labs_esp_libssh2/libssh2/win32/libssh2.dsw": "b497be91f342d18d34c61b8e3d1d9a200c3c17c306e16a71621c467f545ca083", + "components/ch405labs_esp_libssh2/libssh2/win32/libssh2.rc": "29a25c29ed977ba78619a59bc858508caa6f0849607c02da8fa7fe71b6fb7195", + "components/ch405labs_esp_libssh2/libssh2/win32/libssh2_config.h": "d5e704c80aca43c33698bd45059eecde05b098049192bb9f0640af593cdb2cb7", + "components/ch405labs_esp_libssh2/libssh2/win32/msvcproj.foot": "d2cd7c9492045f6a9384010e9cca3c91e2a60c2e54f64680f72d94bbfcb387d2", + "components/ch405labs_esp_libssh2/libssh2/win32/msvcproj.head": "e0739f82a357ab5871aa44790521d50a80b74b5fe638c59ffb41b97c98404930", + "components/ch405labs_esp_libssh2/libssh2/win32/rules.mk": "5f68dc0a3ef0f61d783289c98c00419a0a76a2b866ecd0f86404ca1d3effc12a", + "components/ch405labs_esp_libssh2/libssh2/win32/test/GNUmakefile": "e2c77b03fa88a88d90fe1dcb6c095935ba99b03b56a78f101a373ff208e1369a", + "components/ch405labs_esp_libssh2/libssh2/win32/tests.dsp": "9c206fcca8e6ce5bb88c2278aa7d74ab8cf740d687779ffc66161ea4cc00afc0", + "components/ch405labs_esp_libssh2/libssh2_config/libssh2_config.h": "4d564e905c0f8a3eb92e55df2874b2b9ff8e589cbd6033e466129f107a3dd35e", + "components/ts_api/CMakeLists.txt": "f1cd2808b27affc21540be76b960bb87044b96be6a9859257563469b3724ef32", + "components/ts_api/Kconfig": "f887aa9f114a9715e286ca3d55fe77f98560cbb1cd9b4c63cd55dd5830386b64", + "components/ts_api/assets/lpmu-agx-network-setup.manifest": "8a4e7f5de0570f69c2a6a33cb2ee6c28afff763d364c7999cf70a76bf418769b", + "components/ts_api/assets/lpmu-agx-network-setup.tar.gz": "77ac9410a62eea50b2a5079d3a7adb1012deee1188c03e0a5cfb4609e4e5f636", + "components/ts_api/include/ts_api.h": "06e9e6878b7624461d9f690cecc169e684075454429e9fc21ae09f8563d6ac69", + "components/ts_api/src/ts_api.c": "56635fcd468d3f39fc06a04f6bca4dc319b8ab125b2dd93b3050bc879cf2bc14", + "components/ts_api/src/ts_api_auth.c": "be45df1d19803e7771d70f19bd5cf970f6ed51b3b20f55ad73b529fedf19c66e", + "components/ts_api/src/ts_api_automation.c": "01ac4e75a4e64b51eec7b6e5c8566c01a86ca9fe58bd3774929515f0178a3d7d", + "components/ts_api/src/ts_api_cert.c": "25af390ae3ed16eff746b2b49c3fd5893d418dc91c6106b5dbe1511f2885b7ad", + "components/ts_api/src/ts_api_config.c": "1eaf82f2f82c228de7e00c86fd3d500883107917014a5e506cd24fb60d13c667", + "components/ts_api/src/ts_api_config.c.bak": "d5f055134e303f3d724bcb65e3da8417b2d20876b2909b93403f7a3bba1d7a1c", + "components/ts_api/src/ts_api_config_pack.c": "5aa2d353b773bbd06b6235e579b540c17211534ed5440c4adfb40112f4c96968", + "components/ts_api/src/ts_api_device.c": "7f3714eb9857d069bcf6861a271ce95ed21a86b4446a99fb889486e085e5b7d5", + "components/ts_api/src/ts_api_dhcp.c": "45d3b4ccb5d6bbb3f68e424b5762daa8b0743da1575ef200b315468d65b071b2", + "components/ts_api/src/ts_api_fan.c": "41e8d20c253867f334e9b9517258c7abd6f2f34c935ca4632d27f6a627385432", + "components/ts_api/src/ts_api_gpio.c": "a508837fd3c59b00ba6df75b97e9ad496bc633b44db0167fd703b9d7cfc67284", + "components/ts_api/src/ts_api_hosts.c": "d65c9183c5064a177e594cf57a98142263542de501564d76134730b178483719", + "components/ts_api/src/ts_api_https.c.bak": "a1200dac515be89fabc14dc850c36c9df92f66834876ee25064477444b17de0d", + "components/ts_api/src/ts_api_key.c": "7b06d396f2d49f4bf17bea6eaf45f96a73712502778f912c725bf46b8aea8ca1", + "components/ts_api/src/ts_api_led.c": "d46955f01a5ee7c364c0b549cd4f035857295570f3f7be7ac8d271f684c99849", + "components/ts_api/src/ts_api_log.c": "4887b2be40a0ef3a534f86a66c1a24a7a3f3f3d07446380b7d0c65d62095cada", + "components/ts_api/src/ts_api_lpmu_access.c": "c0e2a0bf52d476a11f922213b2bd4de475cc793c6a3710aa705ffde7101b6571", + "components/ts_api/src/ts_api_monitor.c": "a33e2d70b807d8be2a752ee2a95d3e42991d3d3e84622bd725ea8680fd68420e", + "components/ts_api/src/ts_api_nat.c": "87f254d083090678b3d96fe5923dcba919405ff336608b2a29220692e21cf255", + "components/ts_api/src/ts_api_network.c": "41f60810337f7cb7ebea6646d50878aa753b7942cfa45007666d47fa26162a8d", + "components/ts_api/src/ts_api_ota.c": "0052993718bc857ac770dbbbc9b6067f8db1eefbddee5d5fe9da33b299d4bb78", + "components/ts_api/src/ts_api_power.c": "dc65cbe9c56a8478913f148ef21315878e2d9aa13518d2b20a407e05b8b2d1b3", + "components/ts_api/src/ts_api_service.c": "54638eebb7c4604713e597c1f058791e13833dd407aa9faf906dc4afb767e0ff", + "components/ts_api/src/ts_api_sftp.c": "af147747910dff5c70a21c423284764aa48ccdf0b69ec51307a080567c30c334", + "components/ts_api/src/ts_api_ssh.c": "edbf7f6a4c80f3b15a75e7b39096ca0e6fe6c98ab1cc5c3e3091b5c947646ff7", + "components/ts_api/src/ts_api_storage.c": "2d609316f08eaa00de84649cf52e38fc4c9558d10dce855dfb6c44687e12eaba", + "components/ts_api/src/ts_api_system.c": "e9668b91761222e6ef4f840feeda118e45f769ca9c86c8e9c5c6749b150ab31d", + "components/ts_api/src/ts_api_temp.c": "76dc78ecc8dac1b468e75e239ef57bef6ff84945510d626b291973f12f4b4b62", + "components/ts_api/src/ts_api_time.c": "0ebaa8796a37b1d965b51f9cf5b470d768b74a34c79c6e11184f082979c20fe0", + "components/ts_api/src/ts_api_ui.c": "ca2f0446c6cb0e42b4880fd48be4b7a52fe666a0eae3d9e828ade9289ab7358a", + "components/ts_api/src/ts_api_wifi.c": "54b7eebeced862a7bc75ef17acd9e5bb46faef526373c1a6300564a36bf0b4db", + "components/ts_automation/CMakeLists.txt": "5f6513d53d29951ea58531984c1c4a23d8cf9444ff9784d305cccbd13190472d", + "components/ts_automation/Kconfig": "38cc856f0951f867e771084ad7e22a8f237c4a10358f9f285bb4f4617d1f3df3", + "components/ts_automation/include/ts_action_manager.h": "af18f369c569389caf2ca033f34b234a18b724577334cc5731f9d0d449f85485", + "components/ts_automation/include/ts_automation.h": "fec1551e90c8b0e0acb0b4355c695d90213d94247659db99670c9782c69bdc08", + "components/ts_automation/include/ts_automation_types.h": "e2c9becd036d1322fdf5f40ae67df8a6d23c53f411497368e61fbe557a9d597c", + "components/ts_automation/include/ts_rule_codec.h": "501ed7dbec67e52807997cc905b41bea86d71f119cd4b31b9f460c0e0ba54a26", + "components/ts_automation/include/ts_rule_engine.h": "70d0d72afb2ebeffc278e1c844663049a5624cd2365311c0116f40f057b76a74", + "components/ts_automation/include/ts_source_manager.h": "42f2e1281ea0644a47013d3eb1a35cf6ecfc6115627b75c8fda3dfb7b4e0f78d", + "components/ts_automation/include/ts_variable.h": "136b371f4d0fab848c8c2ae15de4993b8786479af64e4c87974c8e26d1be009b", + "components/ts_automation/src/ts_action_manager.c": "837efaaa4e418681f102b9ae1b610dd05513a53fd820cbf8c55aafb00b2fc849", + "components/ts_automation/src/ts_automation.c": "be565cb980d822cbb6081a32d07e560dccbde6a254a06d0d06c10b92b9113ba8", + "components/ts_automation/src/ts_rule_codec.c": "aebb9914c282aeda99ca089ec1ed2af93efac865ee9b0e2a57d9c6abec9f828b", + "components/ts_automation/src/ts_rule_engine.c": "73e6627c2ed8aade04c3d102186fdb837415d223864a1080f9b7714d7c39b06e", + "components/ts_automation/src/ts_rule_store.c": "e96b4119e512751272ca8dc58fd553052895ecc5c742db9c47c34bf264d7772c", + "components/ts_automation/src/ts_rule_store.h": "ee248de2197d6027037980166f8a90a240214ec2c7a17c0e4097c0820e3add95", + "components/ts_automation/src/ts_source_manager.c": "4287f8ce547c360db5c30af83f62123864831730bd0fbc5b34feb522957beb0a", + "components/ts_automation/src/ts_variable.c": "9740db1f2a06a2526354cf573c1ebdd3c512bab9f9175aefaca38f8eac5c4dcf", + "components/ts_console/CMakeLists.txt": "844bd8be8bd6d63b6c0ef8118cf32b291562982346fdc7246a0d9fd03a586aee", + "components/ts_console/Kconfig": "8b835fb6fc27abc7491581c4f320ec600f70aac4874afcc78b98e280eacbaff4", + "components/ts_console/commands/ts_cmd_auto.c": "e57b47ab327f04911afe72b14edd3685db9c9bdc9a6fe46f90298483a1fd4754", + "components/ts_console/commands/ts_cmd_compute.c": "0d6395aaeaa7a93109ea25c71f53f3af11f7bb5efc1ddca05298a30460d0134d", + "components/ts_console/commands/ts_cmd_config.c": "28dc46db153b4b3a68024d5bc3ec37001df4d6d4bf7cf41e1800c4be30005d77", + "components/ts_console/commands/ts_cmd_device.c": "f3d82977bc6f499f45c04cdb02aebc67756251bc7683270823e40bfad5160b8f", + "components/ts_console/commands/ts_cmd_dhcp.c": "53609fa0ad1af0b5b91eff63b65c87a367f6fd8edec3c68cdcb30dc2f2f84145", + "components/ts_console/commands/ts_cmd_fan.c": "599db48798328646ce71fb26f19734ecf4e634fce9c4aae1da1241d92fd8f9f3", + "components/ts_console/commands/ts_cmd_fs.c": "3f236843d1b1982d48311c4ff5c6ade2e07819cba35b2823dd67e17b77aad5e7", + "components/ts_console/commands/ts_cmd_gpio.c": "33959a8512d0cfaaffd038ed3449ace567764a813fafeedbb722b1fd41dc6dea", + "components/ts_console/commands/ts_cmd_hosts.c": "645e96c17ca441cbd8cae5caf0a3b81d66f7aa9a62972efcb7d86d9acc06f040", + "components/ts_console/commands/ts_cmd_key.c": "78dd3af63ba9ee2f4e29b4b9142d17f860415ebbc5852b0bff9856c5cdb048ce", + "components/ts_console/commands/ts_cmd_led.c": "8d535e208a3ae3777468edcff5b5a01211fd1e02f600777ecf29905cf8669676", + "components/ts_console/commands/ts_cmd_monitor.c": "526c49802f6f34d4b9f5d0504eec76a3a2e06163df2bc3dee6d73a873a404b18", + "components/ts_console/commands/ts_cmd_nat.c": "cd4de61f4135904a1b063f8bcfacdfca177f38fe14f69bdac8fd6052cec0af27", + "components/ts_console/commands/ts_cmd_net.c": "5225f73d760d6da98719bf0c3551abb4366d087174487fb3246169fc232200a2", + "components/ts_console/commands/ts_cmd_ota.c": "403179e5d864a30af5289014fe2ce677cab9cecf6876802baa32d0fdf1cfd932", + "components/ts_console/commands/ts_cmd_pki.c": "85bfa318ace72dd40ac9208a3ad8af11afb33120e2e2b61de3594f2e5be4b16e", + "components/ts_console/commands/ts_cmd_power.c": "77ec359cbe492d3fb90318716c142c2408901f5e50a3c4a14073933cab7ffa8c", + "components/ts_console/commands/ts_cmd_register.c": "33adbed296353e1deb9f97efbf1139ad4c8a7ecbfa3cc661c2236f31529c4630", + "components/ts_console/commands/ts_cmd_service.c": "bb62b73286bec5d6c5f184ad8ddde9657b96042ca4ddbf75dbc60c2bb9fa3388", + "components/ts_console/commands/ts_cmd_sftp.c": "12ef96104441fb58dd07aabcfa32e28dc2617957324460700c75ea43d91e4181", + "components/ts_console/commands/ts_cmd_ssh.c": "7878385dce3d19af0a45e5dd5f264c95ce7cc0a2ee5afcd47d326adbf359c722", + "components/ts_console/commands/ts_cmd_storage.c": "9c7c581d9cbf82ccf5b91eea4c5f4683aef82ac4378bc750394f3236fa479114", + "components/ts_console/commands/ts_cmd_system.c": "1ed44e7f13f4aca20c352d734dea23150346ffc46645dab9f62e9baaac45d2db", + "components/ts_console/commands/ts_cmd_temp.c": "fb163a57281fab7d5a7732e2be9dfde0ffc169dc05d720123d0ee4fe9e6b7a0a", + "components/ts_console/commands/ts_cmd_voltprot.c": "975cf460bccc27660cc93bf0130d2bbd385369616b8ecbb48ff32096f16db3ae", + "components/ts_console/commands/ts_cmd_wifi.c": "c3042a507001b54a14b3f8ff5f32ee5d38b305d156c3267cfac2a23f2e3b3824", + "components/ts_console/include/ts_cmd_all.h": "2f76f6ec1ba074d28deb15efb4d0272607604d0b809a52fdf506b15d5659cb52", + "components/ts_console/include/ts_console.h": "f107554abcf4de2655e2bb129f5bece338ca9126e89a546b102a9bff9d92400a", + "components/ts_console/include/ts_console_args.h": "98084002ced0297f0f92824510271e56af90199442518c392d1fba3907cf624b", + "components/ts_console/include/ts_i18n.h": "9ce79a7c63c72fc49899b7614bf9a751808183de90b5ba2a228e2fffea1f1d9e", + "components/ts_console/include/ts_script.h": "a7f8c453393ac94e2c4d562b1bd8a715a21884ab7fbf1f2e19ea5acbf1ea2abf", + "components/ts_console/linenoise/linenoise.c": "ad81b74f8d3482c1dfbb37c34dac1b40a401ac5384a9c3348046ec66fa51e679", + "components/ts_console/linenoise/linenoise.h": "67d0d645bd392175ee75d4e94f2cd1bdf0eb086679d5fd77a6b90c449dd6d94a", + "components/ts_console/src/ts_console.c": "00407de9165403958c3a33c15425a4a527045ed00ab72820c3d011df52c1a6c7", + "components/ts_console/src/ts_console_args.c": "2d47c6c9ab6bead1302cdb2fcdabd14d6c0304e88a3418997965993c7e471863", + "components/ts_console/src/ts_console_builtin.c": "80eef72644309badf1181b6e98e3dc336ade99baaedfe9fba95d83df82bdfb2e", + "components/ts_console/src/ts_i18n.c": "c3d384a39ba32f27f142accb8dd17b06ca12722546332058add1490eb4f5d994", + "components/ts_console/src/ts_script.c": "034fb13082dda23578b2b20800812b59cc155fe77ed788a2247903c834b9c8f1", + "components/ts_core/CMakeLists.txt": "326c89b533f1a3a18f4a567695ef66aeca7ebe2b53ff9363ca466208e0e65905", + "components/ts_core/include/ts_core.h": "9504ead739f5011bfc7864103464bcd7d8c06eab2242d89391203164e9210197", + "components/ts_core/ts_config/CMakeLists.txt": "84e0791274bf45e4fa2c3373bfbb8f6ddcb2883c3dc7234a15fffd905a2dff9f", + "components/ts_core/ts_config/Kconfig": "7d319983a89dac10bd815eb94af1b0665a471e68709c6500ae298756161931c3", + "components/ts_core/ts_config/include/ts_config.h": "4945666dbcc7eb507f5a740061340a692e5add4ba3a4e5e421bd656d8b24b4ea", + "components/ts_core/ts_config/include/ts_config_file.h": "2d3bab9796164c3c2d945f2abd44e38dbdb37243283a62790275fe7872e65b78", + "components/ts_core/ts_config/include/ts_config_meta.h": "b649ab500111f98ba9035c525a625fc7ca21e0e553db1c978e03b35f24d43826", + "components/ts_core/ts_config/include/ts_config_module.h": "94873dac21ab86cc2f4eb4d7265588457e97e4386602773a3228c49b864bb472", + "components/ts_core/ts_config/include/ts_config_nvs.h": "2ec4ec9940dabd37df9de6f69d314583e1e77546c17fd67ccb5673a50be8a142", + "components/ts_core/ts_config/include/ts_config_schemas.h": "1b7de493a6e88d10155b558510e6ae4a72e31fbc1f77510c98b1ee8912ed94c1", + "components/ts_core/ts_config/src/ts_config.c": "c9a7b95660bfb29539cf323acd0ba66db8359a094347ea23740766a3b9721aaf", + "components/ts_core/ts_config/src/ts_config_file.c": "c61d01fec4b55560963a7995885c375f084dc54ee8ab52b47288eb68cd4403c0", + "components/ts_core/ts_config/src/ts_config_json.c": "be09570bcc58ef2dce1b4cce5968d2a0ce5a5ba0451295278ff16a66b7c32428", + "components/ts_core/ts_config/src/ts_config_meta.c": "ecf781cbcb200e56689bdaea34216cd033bf477eb1087eb1b03413334d2c92ec", + "components/ts_core/ts_config/src/ts_config_module.c": "f2c74dc811a31d4b5d0be2f2105f937ddddc5f52345763715e6fcaa6a74fbb8e", + "components/ts_core/ts_config/src/ts_config_nvs.c": "8dd95d5c09611a856e49770bc30ec971bd313cf759d833a6f97605f1dc6ef0c4", + "components/ts_core/ts_config/src/ts_config_schemas.c": "522aeba7427df30b89ab3ffb66b8637d3cf0c247af7133cdf2c04d45930994da", + "components/ts_core/ts_event/CMakeLists.txt": "c7f2d8ef1c3ac4e5bbfda512be49c5ade6acebf651ae8913e36e3f7e4ddd7506", + "components/ts_core/ts_event/Kconfig": "b1cf0bc9fa8ad38744b11d594a6f3aeb077a8ab88950c9695058e95aaea18929", + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_core/ts_jsonpath/src/ts_jsonpath.c": "115117f7a1281562ede7fe5666ba313cba8819742c8c22547a1ff0d0c9252c6f", + "components/ts_core/ts_log/CMakeLists.txt": "d149529554e03487f45cbf2f04d2989a996b328d94818614a91dfcba97c2697e", + "components/ts_core/ts_log/Kconfig": "35cb224534047beeb071dc83802e4c4532849b38d87e5feb75be5eea0634c972", + "components/ts_core/ts_log/include/ts_log.h": "beca44f4bde1ecba236f2a15d6a9bdd8037b3bb29f395e25b2f8ba4696847b57", + "components/ts_core/ts_log/src/ts_log.c": "c0cb7132cc80baa5ca03edb1adb13b0dfaa136bd4a0fd958307a43960be47b6c", + "components/ts_core/ts_log/src/ts_log_preview.h": "9e05ef9413323fc1ebe476e8fd73cf959767ceac9db7b4a5ddce17839e49b509", + "components/ts_core/ts_service/CMakeLists.txt": "ec3f90c75a8342547444c03165f61c9e9d5dfd1441598ede2aa93cf1711fac61", + "components/ts_core/ts_service/Kconfig": "3ab9397356f4485ed636b1af167714b75fc3d219386b8774ffe3bae6cfbd4675", + "components/ts_core/ts_service/include/ts_service.h": "2bbabd7738c2fb19880e45c0df169e3d5f6a226bbe1affdee030a7ddf8b2dd87", + "components/ts_core/ts_service/src/ts_service.c": "326b3ab1d4a61eba8b9bf43af26039fc4562092cbea19709764104278c79ec2b", + "components/ts_drivers/CMakeLists.txt": "22ee0589081126d02231d52d9e6526b095a4b5c13ce2cc97cb1e5666e848b8ca", + "components/ts_drivers/Kconfig": "55bfa04880f382bce54b4aae233d0f23488bd94ce8e3fac01ceee49477034427", + "components/ts_drivers/include/ts_compute_monitor.h": "b85ce79f490986e6b64ec3b12bef425576b5dec0121c0237f8cab34aab772703", + "components/ts_drivers/include/ts_device_ctrl.h": "0d203054b4b8dfe970d408c706fa1e123973b9bdc52583eec63162eee25a8879", + "components/ts_drivers/include/ts_drivers.h": "56d740b76b1401407f81099e521cd514e617fb1cdd3aaf9eab727a86dd327fd2", + "components/ts_drivers/include/ts_fan.h": "2a30df271570bff942383c46e368f232db484627bbbbb29b77a49a2155304cba", + "components/ts_drivers/include/ts_power.h": "1961071837745a2e5db6290e65bd4cdf8465a6e42b181b24f13ec642a80cc45d", + "components/ts_drivers/include/ts_power_monitor.h": "1e1b1f246f6cea8d05881e9960d2db7fd25c4185544ff8659dd8556d8f68636e", + "components/ts_drivers/include/ts_power_policy.h": "1f8475392cbaab61e90470ee0a246a67f4f8760392026318e2a56ea1058cfbc3", + "components/ts_drivers/include/ts_temp_source.h": "195c577b4f4e51efe4ad19315679dac3944f53eb72bbc94392717b3426067000", + "components/ts_drivers/include/ts_usb_mux.h": "4dde492aa085eab2024a12477036b80583b9e00a6ee3200164ec6b2b5a3b5080", + "components/ts_drivers/src/ts_compute_monitor.c": "dc396f53de43ce72b5ca6c0301d8ec82056648adce0952e0b1012e7b6a794587", + "components/ts_drivers/src/ts_device_ctrl.c": "c30a1cc807542077bd8302a9c6a4be07f286f76acb66e95f787ee9eb5fbdb279", + "components/ts_drivers/src/ts_drivers.c": "e21d531fd3bdf7024fbbd0ac7162d17602775fbe4fe237a3e0fc234ae3ed247b", + "components/ts_drivers/src/ts_fan.c": "4771e2094228dc6586be30910acc60ef44ec16f852684834eb81776e1d867431", + "components/ts_drivers/src/ts_power.c": "02d30bfe6140dcb78a0a0b26e36de7902864b323f64e5d3b6f9d6493b0d5dcc0", + "components/ts_drivers/src/ts_power_monitor.c": "22e16a8a2f0629c28f2c2f2f4d7ab259d2013be1e13943da2d0866d1a379b1d7", + "components/ts_drivers/src/ts_power_policy.c": "bc0daace30a1b4c5c14fe839f03f9af9817e9597661292be4cdf6b81e3e68957", + "components/ts_drivers/src/ts_temp_source.c": "986d608503653d071ee8e06f04560eb74403d2839add61742cc05c004b5fb153", + "components/ts_drivers/src/ts_usb_mux.c": "76687b9f9bcb1081eb2cf08ba6dd49136b3262e806db6be0756d4981bcd34470", + "components/ts_net/CMakeLists.txt": "d6aaac5a04b06bd536336820df0d5eb8c87e27b3087e5df41e640508314b163c", + "components/ts_net/Kconfig": "ddc14968f72310808d23b849248c7cb49411ed43e0f3c268060fb60da2f26e06", + "components/ts_net/include/ts_dhcp_server.h": "64e5e854f9b8fd7182f92dfafe594f3d8f1288ddecbbbec2c89b3aabee950c51", + "components/ts_net/include/ts_eth.h": "9f8952c77ade85741afb38aa48f3fb689a94164a2c598eb6c7df9344948cf8ce", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/include/ts_https_server.h": "f4c25017722b69f2f1bae48df34aa595f15d186ad3ec652b7be9d034e184bc79", + "components/ts_net/include/ts_nat.h": "1721b9c499ca0da09eb402d7db9211604a7a3414b6e2e7cf88169f872365a229", + "components/ts_net/include/ts_net.h": "2ddcd9233f0f5f63a83fdc6f3d09de3118b5b1cced5d9b009b3126c3b872a98b", + "components/ts_net/include/ts_net_manager.h": "6ad22613972f51af05eb6d468c04763808d92c1d6a6b0a7225911b24f9c0d9a5", + "components/ts_net/include/ts_time_sync.h": "e3ebf9da5b0c7b30a50a67fe07547e2c7fefd588474552579f4a2bc15ace8ca4", + "components/ts_net/include/ts_wifi.h": "25614f917387174bbbb7618010885353008e4488262303b314b87b78ae9f0905", + "components/ts_net/src/ts_dhcp_server.c": "800f32ac5097d4d73807496713a59488adfc417a1ea3be627a097cb4c9da0279", + "components/ts_net/src/ts_eth.c": "d2350045f8abe2d3bc1c046a51c5c0016b601f69bfe99ff2bfcdec8cf26e47fe", + "components/ts_net/src/ts_http_server.c": "0c8449fb396246074ef9deb404b2d5f98610f4f22f3c1ce70bf2774711dbb6ad", + "components/ts_net/src/ts_https_server.c": "50e9e0498aa7265739b99d9131eef726149fac255d20f152190d289df16b8ec9", + "components/ts_net/src/ts_nat.c": "e5accbee0cc4b7d0feccecc080b23726af94418f5f2c9645df785eb142a1eb24", + "components/ts_net/src/ts_net.c": "2f363e1c6cad3437449c742f42db70240cc34105942cfd2c2f3a854b226b8f92", + "components/ts_net/src/ts_net_manager.c": "4184c6e23f68b160a511fd8c44baa8133c04596fc00fcec459389ec61c14789f", + "components/ts_net/src/ts_time_sync.c": "d83f4591d1c45de7a89af7126c9921301a06ce2a6cb3890c5d302d491811db56", + "components/ts_net/src/ts_wifi.c": "54fdffed9cde1145b5dccc5e9419a72c94f83fbc395b225e76098be09b01ba3d", + "components/ts_security/CMakeLists.txt": "cdc8e21b6985899e65385ce4b2c92958cc540f19f3445255301b20ad71241c88", + "components/ts_security/Kconfig": "c3d0036c138f0bf227f73558802a24892694e5f8328ecda2ab8007e0aa219a06", + "components/ts_security/include/ts_crypto.h": "371ac3b950f7185eaa21a710c4e823ed806ab337d573cfffdcfe58656aeee8c0", + "components/ts_security/include/ts_keystore.h": "55831771c42ae32640dc6ce1d7755f3487149f71f42d1f1ca7451af2ff675f40", + "components/ts_security/include/ts_known_hosts.h": "4b1244556d046e0057ba0d372498f92d263e43183975d5e55d0bbaea669b0934", + "components/ts_security/include/ts_port_forward.h": "a249f758369a81a7db44f71e4aed0511cd4f5aa932cc4bde33b29c393b5d39be", + "components/ts_security/include/ts_scp.h": "5801a44ef598560d9eef3265ec5b891b494e2682b3049834d3694abe0f86f175", + "components/ts_security/include/ts_security.h": "01cf0f2c1ee2599c0d733ac5d7466e73358fe5483aad23d654c2e6b99c039f35", + "components/ts_security/include/ts_sftp.h": "6d0c9ab1ac7dd3eab5d820798f543be18e2de1d43028dc72ca088b3ec13ab1fe", + "components/ts_security/include/ts_ssh_client.h": "ceb00ed29965279a154e061638b58769e148ea370f5435de48c90c1c8d90f928", + "components/ts_security/include/ts_ssh_commands_config.h": "d1fa1bbc2762bc4accf697db09959396cb5d82bb67ba1806a0cd4f9b45305352", + "components/ts_security/include/ts_ssh_hosts_config.h": "48d27c0cdeb6b0f462d41eaef281b6f2afe6e460b810a61f2f98278d0609280d", + "components/ts_security/include/ts_ssh_log_watch.h": "08677f37f9ee0a3620f6ed38770c4f1977d3b70787e96e57db0f934de5c5452f", + "components/ts_security/include/ts_ssh_probe.h": "697c24c0ff5244397d3483997357a81311cbd24b718d64b845efd96e19979e43", + "components/ts_security/include/ts_ssh_service.h": "73fbddabe3eaed6a191b90b1644eb50eb440509723c92f4a61788c2306596102", + "components/ts_security/include/ts_ssh_shell.h": "0594cdb6f555becc8878609039106e4d986a926be559691dd7785ec7d5d3af0e", + "components/ts_security/src/ts_auth.c": "b4456d19bb701f5be50c08bb8024c8b24eb97820fd47c72c9fda6e1ff334b78d", + "components/ts_security/src/ts_crypto.c": "5ef1140c4f122a49a531de1bff5c48c80067bdcadf2139553c35a59fd5404587", + "components/ts_security/src/ts_keystore.c": "0046e9a9f13a4dd73f932a2861b787c6264ad1597694b3cdc8a9b9eca251ea1d", + "components/ts_security/src/ts_known_hosts.c": "72e2c0c5723cf9fed7c589e46152b5806c4bdcfba565b862305d2fb299ec3844", + "components/ts_security/src/ts_port_forward.c": "b2dafd8ffc849f684cf0a9f332864876951d2d9ee7fd8a69ce7704430d00853f", + "components/ts_security/src/ts_scp.c": "cf328d792705cf8d6b00ecc3b8369ae8360fba977a3147e0a2eef6634a08cff8", + "components/ts_security/src/ts_security.c": "1c4bd91f4ab676be0739b60b826e026a84baade609369995c845b1991a1e2c49", + "components/ts_security/src/ts_sftp.c": "e05a3cd229dcf4344cfcc785755e075b52f94a4276411abbbfb6e7716793a899", + "components/ts_security/src/ts_ssh_client.c": "071b875b4029cc9d0d9e5538ce7a05921a07ec57d09faa45d295fccb7625552d", + "components/ts_security/src/ts_ssh_commands_config.c": "f12fdb5169de9e52db02590bf9d821bc08291b6c24e62f4f81bc54b03574e6da", + "components/ts_security/src/ts_ssh_hosts_config.c": "36d70ff90bef5b0efdf1195c614a33a70b7ed521807c28a2a3b4d918265b2056", + "components/ts_security/src/ts_ssh_log_watch.c": "3843930a4337ea56092d37e1ade0651dd1f6a14c3f5596d33bc83a7880712f6b", + "components/ts_security/src/ts_ssh_probe.c": "810b235d84659426a3181ec594a345e2fd0ac7fc7c1ce765c34265ad1bc05843", + "components/ts_security/src/ts_ssh_service.c": "fc345627f4f2c9417dd0e74fb47b3d77e2cc9f41fd9537bd2f633b0260e5e01c", + "components/ts_security/src/ts_ssh_shell.c": "87412b746f3a18a1937b479592e446eb737cd1f4999c316b662e5435d88ab46c", + "components/ts_webui/CMakeLists.txt": "53e02258893758d55edf0debef2e0694b154ecccda65ab3b5bb5d34770c39d45", + "components/ts_webui/Kconfig": "6a1fc77d34f7c635b44a922f4c7c9fb96832a9f6bb433967c26e3bdc451ae286", + "components/ts_webui/include/ts_webui.h": "374e230b4f0d016adb2373acd2e6431cf537eaeb8f7f84efcf53523d6dad0402", + "components/ts_webui/include/ts_ws_operation.h": "4a31681f9e5d0041d2627b5850b23c083e1b0ca3b876acf959adab5955611512", + "components/ts_webui/include/ts_ws_subscriptions.h": "edcfedcdb48cc47bdd776218d43f362f4f2feb84f0a8bd347b465e3dd751e3ae", + "components/ts_webui/include/ts_ws_transport.h": "4c7b996ed4e6a578ce7daa1a02a13729795bd4dca2e66eb8b49895b6f59f36ee", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_api.c": "c8225f3fc36be3446947e205932a3d43340665d687b81c23c16556f3be8dc9b8", + "components/ts_webui/src/ts_webui_ws.c": "cb8f801a18672c24636fe744cacf0f1e0379f75b579bcd4869bb9c9d8e541949", + "components/ts_webui/src/ts_ws_operation.c": "504ce5caa9375a792692eec681a86bf4515aa5c2d28e758d67df08117b6fe865", + "components/ts_webui/src/ts_ws_subscriptions.c": "9f8d2f33a374d6992a1ef119cd20a791244e44abc8d7cd66dc906b4896f764fb", + "components/ts_webui/src/ts_ws_transport.c": "e2eaeb31d00d7996a84badc669ca5587628c63b044c9a8014e587e84b5ab37f8", + "components/ts_webui/web/css/style.css": "30dab8799ed2a8b0a5da49ec84202b30f3c951779ea4533e847a53b2ac9b8dff", + "components/ts_webui/web/favicon.ico": "1ea04b690d7fe816da5efb405c13f9cd953366026eb3553e214de8d5df0d3648", + "components/ts_webui/web/fonts/remixicon.css": "b2218eec4e02513f0feef46f74f13c852152f54eafd83d1274057e3895f0ea1c", + "components/ts_webui/web/fonts/remixicon.woff2": "e92dc38bfb1d15dbb9d9ca9e645754f68e7c5b224e33c45a17048bd0cf2407a6", + "components/ts_webui/web/images/README.md": "f4429665c315cdabc2a935caf0f1423632dd7cbff84f34914965969217102237", + "components/ts_webui/web/images/favicon.icns": "bdc873fa7bff5e1888d80273f99f22d97d3719d4b17419e68e64eafd85c2b039", + "components/ts_webui/web/images/tslogo-128.png": "f09ac97789726872277a0399338cd9bfd0493752de930aeb6b2c6f7b0a864c3b", + "components/ts_webui/web/images/tslogo-256.png": "55dc7df59429c23fdc531baba002b7b23f5a4f2be0f29b2ecc5098f3df059da7", + "components/ts_webui/web/images/tslogo-32.png": "64e4bce72f2b13c81bef5b46ae919abeeb47f98571cf5e55460385880731810b", + "components/ts_webui/web/images/tslogo-48.png": "41f959e327dca63386a2f254b8a245a6fa151904a06eae93ae6c449277467f70", + "components/ts_webui/web/images/tslogo-512.png": "b7508585c46e16fcc7d42c52459ab55df32716aea85a10a560cd64de7cceb8e8", + "components/ts_webui/web/images/tslogo-64.png": "a0809405c5632eb4bf1f1b4783175c2b92b25fc522f5b0682a35d3cfa1c58752", + "components/ts_webui/web/images/tslogo-original.png": "9fb0ee8532c2d572d8b235f7586d225f00609cf8defb98b59cf55ae749e83ed1", + "components/ts_webui/web/index.html": "cb1baa1bfbd2fac00a5fc55caa5442da07ab83b99996af52a41fc5c7e6e98092", + "components/ts_webui/web/js/api.js": "6fb266abb3780a0d402d86ad95a3644b8e1f488136ad44dc18ddd83caaa8dab4", + "components/ts_webui/web/js/app.js": "ad63a38112eab45af87da091f3536156614db526bb85f2c83bafa7867439230b", + "components/ts_webui/web/js/dragSort.js": "7c5b9159cb8bb88b35222424db6d8bd822d3960899d5c090c17955700d6590af", + "components/ts_webui/web/js/i18n.js": "2eed1c54b4ef89bc2e4221a3fd900e88bd8d7a11064a04d97dcc3decfdeedbd8", + "components/ts_webui/web/js/lang/en-US.js": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "components/ts_webui/web/js/lang/zh-CN.js": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "components/ts_webui/web/js/router.js": "1e73ca3bf272a54aea8c516809e09e10f257b620bf66311bbbe358693fe377d5", + "components/ts_webui/web/js/terminal.js": "6d93870c3b33b1888388f3a288cfca581a3034a2a212e1e4130853d1aceda581", + "dependencies.lock": "8829663e7e611b621579e0f8d27d10b3d80e9a969d167e875f7b78597399a482", + "docs/repair/ws-project-v3/baseline-console.c": "4b4edc6e2be0dfedda745d998232bafe99e12496d2ddb8af9f4bb04a5a1bb526", + "docs/repair/ws-project-v3/baseline-fixture.tar.gz": "46c8e84c0eab0da717f5755a43f2c6b1cc6aed9219018de38cd8fa27fb279608", + "docs/repair/ws-project-v3/baseline.tar.gz": "a7853d50f409423c086b7102d979c6b5a6cb1744dadb40b73de47e4390b46599", + "main/CMakeLists.txt": "c229d6b43e670fd75469edd541ad9ef51e0be3985b824ffe21e17cb8a006767c", + "main/idf_component.yml": "3f13a29a2b12e63ea4917315fa77f3481a0e26e976ffd90246312765105a4e58", + "main/main.c": "63dbd073aac40ae7ab31e92f2d52ad3f27c35fa71ade79f18c306f582bcaf40d", + "main/root_password_reset_main.c": "12d485ef6308067aaf112d8bcef71f09ba2ac60aa83a99d576635b102dadbd6c", + "main/ts_core_init.c": "ad9b89b44eef49a72117197da3e2d44a0a9ba73cbf5d1a4c7c6a7e123ea41e1f", + "main/ts_https_retry.h": "8237eca2d52e4424f9ba44674bf9202f93bd43c10f401446c17aabbcc2e5532a", + "main/ts_services.c": "697ae1b5d5472c60a93111ae21585ea23d7ccabce8e4f89b96e5982af10d7639", + "main/ts_services.h": "9631bcb3efdf01739163fde59553f50914da4eacbdb2f3f7eeb72e51a4c83c1b", + "sdkconfig": "1340e033b5865e39dd6b8c3516dffb27d01da5aff41127c69b583cbfb99acef0", + "sdkconfig.defaults": "153efe0e103cc3d7d3d6e330b931e2565a1dc92132af057b9caaf31d13c45d4e", + "tests/certificate/README.md": "7bf3264601fb4f4ae4cb66ecf7abbbeb6fd397e252fc8199d85bae154c2cec8d", + "tests/certificate/extract_lifecycle.py": "3504100b259375558fc0cd24511bd3467ebba6808c8ce9354f94b5889ea7589f", + "tests/certificate/generate_fixtures.py": "aabf3b99598eaa3c8c9e819ebbd216efbf31ccf1d775ad4df39651fa3c0dc91d", + "tests/certificate/run_host.sh": "3001b2faa766c3394e0cef4a5f6f6b09211d90efea23dc582d7d867844905982", + "tests/certificate/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/esp_http_server.h": "3b4e383c6b7f5e2f4325e900d489478f102fe12af0ee4a95edd61276ee49e626", + "tests/certificate/stubs/esp_https_server.h": "f9bccd26c2c5601e735a974931e3aa1d406f759c02fde1952584ab1d8a81a44b", + "tests/certificate/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/esp_netif.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/esp_tls.h": "928ef7af73cf8b4fdbe9b851f3e062ba858fdfc6f1833e8a90dc5645e0ed60b9", + "tests/certificate/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/lwip/inet.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/nvs.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/nvs_flash.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/platform.h": "638ae2aa0b9bc57fed9f1e0659ea9f54a524c854d0300ec7f8c338422977b59e", + "tests/certificate/stubs/ts_core.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/ts_crypto.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/stubs/ts_time_sync.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/certificate/test_api.c": "8ce88089c351c9cf03c43e2476c272fdfb8f15541e3afd78527177afd6ba21fe", + "tests/certificate/test_coordinator.c": "d4defab81ea03df0f914c0cdeb957201c5742c36b264a2c66c8f02bf9dfbd767", + "tests/certificate/test_lifecycle.c": "48ac2284a0197245c27037fb9406bb838c5e4b97e10835f8f861f6865752f11c", + "tests/certificate/test_material.c": "316499dd0a2424b0aab17d4e22b982ca0ae26101f5c21e050cff66a4a4b676d5", + "tests/certificate/test_service_stop.c": "ff3164f1846931e633d870634de8d4d6de8eebc5b94b703ad4b235ec8a7affbd", + "tests/certificate/test_service_stop.sh": "24848edbf13b1cd3624051748b11715b2ca11acc2b2dca709ce5342d11d8a8f0", + "tests/certificate/test_time_cancel.c": "ac166250ca51ed675329c05b533a025d10c8e4b808140e6c45b1c4bf5aba533b", + "tests/certificate/test_time_retry.c": "cf5892bb531da37e7b8d8177ce788efd9b20fc8617dbe3436d23fece8a392aba", + "tests/certificate/test_ui.cjs": "4223157b9cf73a7f0835a795c53951d0105947621709f3ab720bfbc77cfffa83", + "tests/prompts/README.md": "ae4c5e8cca1dae0c7ec4e54d51b58977a6e15a743fdedc32215111ddc4bd5b13", + "tests/prompts/browser.test.cjs": "59e7f77387e015d7d8b3ed926750f1fbf6328059d52b82bb79cbf973b590a1aa", + "tests/prompts/harness.cjs": "7c176507bb17c57abf22d73c5399b34cd8e221fb9663c4e5efe7ac3d168f944a", + "tests/prompts/ownership.browser.test.cjs": "1938411e7cc76ecc190b3469c58e58fd8aaa4a080ede60989190b4abd1147903", + "tests/prompts/package-lock.json": "8bef9925fb843348d3bf83eea1953314108e97f1db9c5972f4e8bf6741269a7a", + "tests/prompts/package.json": "180e0ffb285f1258b7a87ba2688e88c7c454ad7a4de3a9c56daa4c5346a7eae1", + "tests/prompts/project-cross.cjs": "7928610e031f5e0b6ad001f14f0dd5ac39f534dfea253108747f433ae5e92a76", + "tests/prompts/regression.test.cjs": "c372b74e125b361103defe66017c3eeb286fea9975cf4f3167ed5cf981050516", + "tests/prompts/static.test.cjs": "e8a08a747786a84efc6b976545e6d929ec3cf40278c0166b9bdb6b7a8fa810fe", + "tests/release/test_release.py": "e25d21c5d1a49c7c5045b43b70a8c2a58e7a7b0cd174cbd0de22260651a8063e", + "tests/runtime/README.md": "63b78f7e2b2dc6573fc02af35309ddc9b7fd70b359b5bf977051d9b907a58646", + "tests/runtime/extract_engine.py": "305506441b6015504934691dbc8c015d1a7261439ccad8ca36ce9e98cc554060", + "tests/runtime/run_all.sh": "e3020ad2de3b71a57add48332b7b001441f0a05c90fa9b27f3987bfd7360495d", + "tests/runtime/run_codec.sh": "b5aa59598d87f0e9f3828db781a7e37209bb85d343b30077c8aeedb65e54a7ca", + "tests/runtime/run_engine.sh": "f01b742ecdef37d53d704c7d71b1bc3da08d5cb94995e4e9d41bf89f6d51d7ce", + "tests/runtime/run_log.sh": "bb93124e157753f0c625392895b9e2c4123150d4822163d52ec7cef1287e992b", + "tests/runtime/run_service_watch.sh": "1abbbf9c0a3663b0384a907afccbb232721ace5eb52bc808eb9e62a7f6f186b1", + "tests/runtime/run_ssh.sh": "195c42d63b8fffd628d351f511bd577b2669af4279a0a393cc6975ae9fda3fa0", + "tests/runtime/run_store.sh": "5318c61a4fbb3481af4c945cda4cff1a220ab713d872cb24f54cb60705f328b3", + "tests/runtime/ssh_stubs/esp_timer.h": "82a7c14acf5d1cdcbea1b23bab880c69562da88013adc34ff5f2ae2115fb08d1", + "tests/runtime/ssh_stubs/freertos/FreeRTOS.h": "b3adf106d95b8934f690943f2921308b90be5b766c4c8ba250c792de56400201", + "tests/runtime/ssh_stubs/freertos/task.h": "b3adf106d95b8934f690943f2921308b90be5b766c4c8ba250c792de56400201", + "tests/runtime/ssh_stubs/ts_core.h": "12b3fb536445082148e1e0e99bf14fc2b5c543ec212c725a904007210fb6b5b1", + "tests/runtime/state_stubs/esp_err.h": "568bb564e6e567e055990894741eb97246bc07eea4754eb0bd1985c455ef9f1a", + "tests/runtime/state_stubs/freertos/FreeRTOS.h": "5320da8cd50f171f0cf9ed5578748f5d0bf1485bacc2bd25e7ee01fd9fbd3dbc", + "tests/runtime/state_stubs/freertos/semphr.h": "12824e4dc80489b9e8f6205400dd8690c817a599b67ea049b1316459889d35d1", + "tests/runtime/state_stubs/freertos/task.h": "3861b64b31ed63d72e09b26fb04394804c5a3edb45c32e1837f8ed39a39a2a29", + "tests/runtime/stubs/esp_heap_caps.h": "ae408378b6f415e879e2530ecb9e64aa304b76957cd5726f9c54cd672e7d2d39", + "tests/runtime/stubs/nvs.h": "260376fc612ee376562a83298df57771766c77c7e9dc51882ac105708f0b3834", + "tests/runtime/test_codec.c": "63fe28470a7893797d68310d37531200f41d840cc08a5a0213e78bd8ee307e64", + "tests/runtime/test_completion.py": "ebd2b5d936019196aa390190d0c063b1c33a73a9eb309d88b39471ea198b74c2", + "tests/runtime/test_configuration_protocol.py": "e57b3e83ef08b5ee75ea2dc63427c39e0d14163bb9e1cb8f278adad863d605b2", + "tests/runtime/test_engine.c": "22c8d14d18a5ecda0148ed5594ef2300bbcb0bb14c478eda1677510a4d7c5994", + "tests/runtime/test_log.c": "b25800aa17328586173e1e8662e71bac0fa9d6db1671942d68e99d01a6fb631a", + "tests/runtime/test_probe.py": "326504cc98b3e50e3433608f5b80d7f4cbff9066d6d6da48042b199eb9817edf", + "tests/runtime/test_rule_reload.py": "8999ff799c246ab5d2d7e67fc177239e5c19c39b28e8c2048f966ba83d674c6a", + "tests/runtime/test_service_protocol.c": "5e9783aa45015e5d86772073524ea7f7b51da4f0886efd65f12fc8bc93a1c6bf", + "tests/runtime/test_service_watch.c": "74f127b262ad52bb8479886a30d491e17c88c0511dddcbed4de26aeb7e6525aa", + "tests/runtime/test_ssh.c": "a031d28bb3921301ec5e22093700dc50a0ba16225743b686792eccb390cf5bb6", + "tests/runtime/test_stop_protocol.py": "67a64d27d74c91b66ac045febc0b7b165dd17612544587ecef738d60cb0dd727", + "tests/runtime/test_store.c": "cf54744603a08dfb940a79654a7a6ef47d67fe8eff438b69dbf6cf53820b0f37", + "tests/runtime/test_ui.cjs": "92ad6bee1264fc7822f953a979ca0ba1f32a0f9d3c5338ccf765f2d2776379c4", + "tests/ws_subscriptions/README.md": "e2a186d0cc38c5a2df86207cde9f371365b95e678908b15943a7556fe57e5ada", + "tests/ws_subscriptions/baseline_operation_adapter.c": "0b0703b144fa8fc7d412110e55b4d7d2010196e9422deb78ff00185059a5af05", + "tests/ws_subscriptions/measure_project_v3.py": "ee2d07f747bef0acdb64a8479b8aa7bba8dcd7d0f63c7d9d0cb5fa63c9fde1e4", + "tests/ws_subscriptions/project_driver.inc": "f114c2259edf06a8e7d1693d01c500ef52c7cc3be33796610dccfe18f8820234", + "tests/ws_subscriptions/project_stubs/ts_core.h": "8f68e35b813b7df0619258a88d000993d7e5b17174fd48b23057fdc23562a900", + "tests/ws_subscriptions/replay_control_baseline.py": "aefd5ff8bc6ced036c9fec466bef70bddb8b66949b4eed3994cdd109fe2f255f", + "tests/ws_subscriptions/replay_operation_baseline.py": "ba26a739d9dfb4b30b4e10ac0b3955994738820b85a156406dcaaa9518382cc3", + "tests/ws_subscriptions/replay_project_baseline.py": "aa1886bcbcdcdb189d751e2b7486324926a1ca82a525010d75b304263bb2a828", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/run_control.sh": "e2853acc8652b99dfccca85d25425b870996e7bfcb03a5cfe021b76e66d0139e", + "tests/ws_subscriptions/run_f1_f2.sh": "8e804b7a5c66663a62da53f9027b175722034e5cce77ba152aba8ad13b527935", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/run_operation.sh": "bf9d6db03b483d4b74db26e464efc73b673648ef82565edf987e6f275c9ee6c5", + "tests/ws_subscriptions/run_operation_adapter.sh": "1a5b900b4c6aae1619b86a285b6371a683263304db90a81d82477d8fb750d3f5", + "tests/ws_subscriptions/run_project_bridge.sh": "ae17f7a34e725e283652aaff12544b2d80d6b1a80baf6c49ec3ec520e5b5a35f", + "tests/ws_subscriptions/run_project_v3.py": "d7547e29d4da73cf644e5e26330e6c4467c7e424f77bed3c8d7c90945ff4c82d", + "tests/ws_subscriptions/run_reviewer.sh": "2a957bb5d4e0ca0c357ec32fffb23aa60c75019b60cc4c5c33d468d389013ea8", + "tests/ws_subscriptions/run_reviewer_baseline.sh": "6ea73543f64c6de65f59480300cf2d73ece85b798a7a430df5b55f2adae1bb96", + "tests/ws_subscriptions/run_shell_driver.sh": "a689485f668d9c11cb2ecd3b9274b2ceabc0fc6a791cffffcfa923733c70bd19", + "tests/ws_subscriptions/stubs/esp_console.h": "f97fca9ebf2a497277d9ac5af3581a2e83789b4acf3e8b125e0f36fb27210151", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/timers.h": "fd6abec4a547b6e9caed8f0514a08ead4223303736dade89179bb8812a2a5d94", + "tests/ws_subscriptions/stubs/platform.h": "de005401b26f9dce9028db4bbc656ea72e55730535769be4ddf31ccec072c2dc", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_control.c": "7e70ad841a86f6c39a1274f715502991e37c7aa1b7802f7b3dcf805a6aa7d917", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_f1_f2.c": "7d4907e42f3a9c7110055acb6ca667abd62a5f16712306c7dde6b85ec285c9b4", + "tests/ws_subscriptions/test_init.c": "49b7ade237c4fe5df5fe683f4ec731c222cc4939b91b19d976471e99d29173c7", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/test_manager.c": "a1b46f3ad3a877a5cfd1235e7253418aec965c442a5c21ab811a68f1e70be8cd", + "tests/ws_subscriptions/test_operation.c": "c28fd00d191f92bbe8722033a3dbf5d7c6bcc54e054c06acff4429fce149a4e6", + "tests/ws_subscriptions/test_operation_adapter.c": "26c0101af525910b184b076a9fc849d237c0072455fb7883db11d5cf18bb1cb8", + "tests/ws_subscriptions/test_project.c": "c8026c5105688edfe0e06e502bddcd7e44fcafb2def960bec53d773b6135e675", + "tests/ws_subscriptions/test_reviewer.c": "65916f6af7fb3fe00d00bf6999a55f441422b35d4d95b3f801d9cb9b0f591c54", + "tests/ws_subscriptions/test_reviewer_core.c": "7669567ad82171ae32102779e4fc98c4b88871f9e9f761600a21623378882ef2", + "tests/ws_subscriptions/test_reviewer_http.c": "2b9696ac9dd86be96db383392d3bcf61f81a5ab2e881933d767aad8f91d30c00", + "tests/ws_subscriptions/test_reviewer_service.c": "3fa82db0882b90d69450ddcd7a50e5904ae60e2cab8e62ea11656ac4c21e2890", + "tests/ws_subscriptions/test_shell_driver.c": "629ccb086c696e74b65c7ec7054022d65e2c6891cb8af246d9438b2fffd0f547", + "tests/ws_subscriptions/verify_project_assets.py": "0ed7406a6927115f4574187158e53bd085d6cf3afc2962254c62133c839c9c43", + "tools/bdf2fnt.py": "dc156a74f206b95efd2eb5887251c55ef9c41b85330240fe2615231ddb084ca1", + "tools/build.sh": "2cb7ce21128f336eccbb75fc553341a34bf3ef3e65e4f5b99c5b09b476703466", + "tools/build_root_reset.sh": "2a59ab3eb5ae0d075ee9bf3f17582fb779c9f39c6814969bf99ded81fbf4202f", + "tools/check_release.py": "4a3a7c34bd1a0c67e9ed8d38e7daf53feb73b289826260af09fd20704d2c4d05", + "tools/gen_version.py": "92c1db10137f2e2ef8ffde87a8143e25a8bef1ab89b939a911b2ed1bdb7f650d", + "tools/minify_web.py": "34e84dee8c141abbbc130956aa089df01ab3df78251bc89f66f8177cf2f619e7", + "tools/ota_server/README.md": "649596da0058c8bd7dce3388161711183e53078f3ac82401278f7f44c4d4e290", + "tools/ota_server/ota_server.py": "9a3c8826315fababa41b20f4f7c8ad37e3f7e507cf3633d0b5c15abc8df78356", + "tools/ota_server/ota_service.sh": "1b5145c396c94629a1605efd3dfc7ca34941a0d182327b09a168a31495972d5d", + "tools/ota_server/requirements.txt": "4dc664dd1442dea748a7c57a4645d2f0d7d4d0b7b9c9353f628c1cf1e8a6bb2e", + "tools/ota_server/start.sh": "d91b14128fe69285848c02aa42b141a3c3c958c6743c42ca2c8e48f8bb50bdb6", + "tools/ota_server/tianshan-ota.service": "f51c57579dc4e9c5bada13fb5476e9f0d7a9c8777c92278cfe5caabb9e900432", + "tools/pki-server/.env.example": "1d72a9b1c85627ebe631e709eecbf1b8c2408afddb404e0c30113a5f837470e0", + "tools/pki-server/.gitignore": "edc02d8bd09f62823287a0f4c1f90c003838d875810ba6705ba5ab70ef643643", + "tools/pki-server/README.md": "acc80cf8d621a3b1dbd4605e4a8d8d580cfe9111957e6224c0545ae578585aad", + "tools/pki-server/app/__init__.py": "d6e959bfc8628a76e60f18377a176c3c201b55d0d42c4d068d43c353f077417d", + "tools/pki-server/app/ca.py": "fc3ac5216f92393647f25f95b881e423e9cdfa0ee5272c1b8f93ae45d66f9f90", + "tools/pki-server/app/config.py": "afc6635c27892a257dbcd1bf9b815fa7353654d5d11a483a2b79cfd0c9c09c94", + "tools/pki-server/app/database.py": "80355d2a94962a2ef36c27c719f543dd8f7094554a01aca8d3b85041781546a3", + "tools/pki-server/app/main.py": "43b93ec82f7ba9aaa9589e25a0ab0576e74eb00b28e8b9fc842ee1ae4f524dd0", + "tools/pki-server/app/models.py": "b38b398d22b4ed6bd1796c461e29dbf3e538aba4b601e9725214f988ccd2ded3", + "tools/pki-server/requirements.txt": "8ccad71c5aefadd47d5b9aed26b9ef339ab64c815681e702c270328984f841b1", + "tools/pki-server/run.py": "46fa2c73203879a8079c32e52ece0a2d146a7c2ee502ecbee9a0ea40b998ceb3", + "tools/pki-server/static/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "tools/pki-server/templates/index.html": "4bf66c95d18289512f20c27e124b01d5d42de90ae86473f471e9bbbb63ab9f91", + "tools/pki-server/templates/login.html": "0a15f2e1a947ba11e9316f046830152178f3d4fe5f55561399a2f671c09ecd9f", + "tools/version.py": "15ce939bf632dfd2ce006a46cc8e31f9186215dbc824f6ba4a07ebfd9bee5315" + } +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/impact-contract.md b/docs/repair/ws-project-v3/impact-contract.md new file mode 100644 index 0000000..6664eae --- /dev/null +++ b/docs/repair/ws-project-v3/impact-contract.md @@ -0,0 +1,39 @@ +# v3 项目影响及端到端契约(先于实施建立) + +本轮基线/PR head 568b871;PR base d6ed947,main。只本地修改测试编译,现有三项未跟踪目录/文件保留。累计 PR 差异见 cumulative-files.txt,不把目标分支旧缺陷当本轮反例。 + +## 功能与依赖覆盖 + +| 链 | 真实入口和消费者 | 本轮覆盖与理由 | +|---|---|---| +| Shell/普通终端 | router /terminal -> WebTerminal -> /ws ws_handler -> SSH control/terminal handler -> operation/TX -> terminal.js handleMessage/handleSshStatus -> 下一次 onData/exit/restore | 深入。请求 error 与 ssh_status:error 的副作用冲突,模式、提示符、输入和恢复需双向验证 | +| Exec/自动化 | /commands、/automation -> ssh.exec_stream/cancel -> executor -> ts_ssh_client -> match/variables -> app.js handleSshExecMessage;rule/action manager、service/log watch | 保留本轮前状态/取消/匹配;控制与生命周期全套,runtime 检查真正 driver 的取消/总deadline | +| Shell 下层/CLI | ts_webui_ws 与 ts_cmd_ssh -> ts_ssh_shell open/read/write/run/poll/close -> ts_ssh_client disconnect/destroy -> libssh2 | 深入。0 字节不是 EOF、非 RUNNING close 泄漏、EAGAIN 无限等待直接妨碍错误分类与 stop。组合测试不得 stub close/free | +| 遥测、日志、保护 | dashboard/widgets -> api.js subscriptions -> manager -> TX;power event 全局广播、terminal 角色/log level | 相邻共享 TX/角色回归,保护配额、公平性、旧日志代次不改变 | +| 停止销毁 | ts_webui/service/HTTP/HTTPS -> ws_stop -> creators/producers/event/log/worker/timer/TX drain | 深入相关 shell cleanup;R1/R4 及证书生命周期套件覆盖共享依赖 | +| 保存/证书/文件 | router 配置、security/pki/files -> api.js request/requireApiSuccess -> API/service -> app.js | 共享 API 帮助函数不修改;运行时、证书和全部提示 Node/Chrome 回归 | +| 其余硬件/网络/LED/风扇/电源页面 | router.register、app loader、ts_api 注册及 main/ts_services.c 服务注册 | 本轮不改硬件/API策略,保留 host/浏览器冒烟;不宣称硬件验证 | +| 发布物 | ts_webui CMake WEB_ALL_FILES -> web_optimized/minify/gzip -> www.bin;HTTP 静态 no-cache index + immutable JS | cache key 配套更新,核对原始/压缩/产物;版本/工作流不变,release 测试保留 | + +## 消息与用户行为 + +| 事实 | 生产条件/对象 | 兼容消息/接收者 | 前端状态与下一动作 | 资源 | +|---|---|---|---|---| +| 单次请求拒绝/可恢复控制错误 | 非 owner、参数、unsupported、明确可恢复下层错误;实际请求 peer | 既有 type:error,message,只给请求者;不借 ssh_status:error 伪造终态 | SSH active 保持 SSH route,不写本地prompt、不恢复、不重发;connecting 无 active 时结束当前失败尝试;普通终端保留原恢复契约 | 请求 borrower 退出,不关闭有效 op | +| 新启动拒绝 | 参数、另一个 op、容量、创建资源失败 | 请求级 error;已有 active 不变,真正 waiting attempt 返回 local | 只清本次 connecting;可手动重试;不抢别人会话 | 未接受 op discard 或不创建 | +| 创建后真实启动失败 | 原 op connect/shell open/readiness failure | 原 op ssh_status:error(唯一终态) | 清对应 SSH,恢复本地终端路由;无自动命令重放 | v2 close/settle/cleanup | +| 正常退出/真实 EOF | 原 poller/服务 owner | 原 op disconnecting 非终态、closed 终态 | disconnecting 仍等待关闭,不提前写本地prompt;closed 可回到本地 | 票据/投递先结算,真实下层对象释放 | +| 致命 write/read/resize 或不确定写入 | 原 driver state ERROR/CLOSED,部分写或 deadline 不能安全重放 | 原 op ssh_status:error,说明远端结果不确定 | 退出该观察/会话,下一步手动检查/重连;不重发输入 | 有界下层 close,保持原 v2 资源协议 | +| 输出观察失败 | TX done -> 原 op failed | v2 fallback ssh_status:error / ssh_exec_error | Shell 退出观察;Exec 业务不自动取消 | 原引用/终态不改 | +| Exec 取消/业务结果 | 现有 exact ID/first cause/business end | 原 cancel/done/error | app.js 既有身份匹配、不确定提示 | 原 executor/timer/结果排空不变 | +| stopping / 普通终端错误 | 原 WS admission / terminal handler | 既有 error | active SSH 错误不切 local;普通 terminal 的 Not a terminal session 恢复保留,仅 local 模式可触发 | 不重开新业务,不递归提示 | + +公共 ssh_request_error 的调用点分为 connect 参数/准入/分配和四控制入口;不会全局改终态 helper ssh_close、startup statuses 或 operation fallback。通用 error 消费点为 terminal.js;真实状态是路由依据,不新增按英文/中文文本识别 SSH 生命周期。已有 Not a terminal session 兼容恢复只保留普通终端上下文。app.js 的 Exec 消费者不复用该 Shell 路由。 + +前端所有 socket 回调、重连/恢复 timer 和销毁绑定当前 socket/实例;旧 socket onclose/onmessage 不能污染新连接。WS 关闭清掉 SSH mode,重新连接只启动本地 terminal,不重放远端 connect/command。 + +协议类型字段保持:error 本就是请求错误,ssh_status:error 为已接受操作的终态;本轮更新消费者副作用以匹配这一区分。旧固件会把请求错误发为终态,新页面不能安全猜测旧帧;支持同一构建固件+www、刷新并重连,不声称混合版本全兼容。保留同连接 Shell 缺操作ID边界。 + +## 反向审查补充的同链依赖 + +CLI `shell_input_callback` 的 Ctrl+\ 仅登记 console interrupt,原 run 不观察;纠正零字节 EOF 后必须同时兑现用户退出。采用现有驱动状态上的 `ts_ssh_shell_request_close`,仅改变本地循环,不释放句柄、不代表远端已停止。CLI 原 owner 继续 close/disconnect/destroy,WebUI 继续原 op 关闭入口。真实 CLI 回调编译组合测试与独立 baseline-cli-exit 反例覆盖。 diff --git a/docs/repair/ws-project-v3/optimized-results/browser.json b/docs/repair/ws-project-v3/optimized-results/browser.json new file mode 100644 index 0000000..a3ad5bd --- /dev/null +++ b/docs/repair/ws-project-v3/optimized-results/browser.json @@ -0,0 +1,31 @@ +[ + { + "name": "browser", + "command": [ + "npm", + "run", + "test:browser", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "name": "cross-browser-en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + }, + { + "name": "cross-browser-zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ws-project-v3/optimized-results/browser.log b/docs/repair/ws-project-v3/optimized-results/browser.log new file mode 100644 index 0000000..31d53bc --- /dev/null +++ b/docs/repair/ws-project-v3/optimized-results/browser.log @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (787.428042ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (349.116875ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (383.910375ms) +✔ en-US: initial language failure blocks controls and retry recovers (401.842708ms) +✔ delayed language package and rapid switches keep the latest requested language (348.494791ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (489.072667ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (329.183375ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (403.808042ms) +✔ initial delayed language keeps controls inert until the real package arrives (370.800083ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (434.553792ms) +✔ terminal can initialize after failed resource load using newly served resources (432.639167ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (815.186ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (282.880042ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (282.666375ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (321.934167ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (303.012958ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (357.993833ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (226.695334ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (203.878709ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (228.214042ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (245.214375ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (220.98825ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (266.538083ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (306.436666ms) +✔ R3: late validation cannot revive an old apply entry en-US (313.097333ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (266.622042ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (235.827459ms) +✔ R6: fixed upload destination and separate refresh failure en-US (250.113167ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (243.153708ms) +✔ R2: authenticated startup initializes once (278.597625ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (403.263042ms) +✔ R4/R5: newest result wins over late success and late failure (221.988833ms) +✔ R3: overlapping writes to one path cannot claim current verified content (239.142834ms) +✔ R2: disposed page only removes its dashboard callback (257.872375ms) +✔ R2: stale finally cannot unlock the new page read (232.894542ms) +✔ R1: delayed sign-out does not clear a newer sign-in (213.767084ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (298.448541ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (342.619ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 8291.951292 diff --git a/docs/repair/ws-project-v3/optimized-results/cross-browser-en-US.json b/docs/repair/ws-project-v3/optimized-results/cross-browser-en-US.json new file mode 100644 index 0000000..c68e2d7 --- /dev/null +++ b/docs/repair/ws-project-v3/optimized-results/cross-browser-en-US.json @@ -0,0 +1,714 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "state": 0, + "writes": 1, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 5, + "writes": 3, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "state": 0, + "writes": 3, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/optimized-results/cross-browser-en-US.log b/docs/repair/ws-project-v3/optimized-results/cross-browser-en-US.log new file mode 100644 index 0000000..238358d --- /dev/null +++ b/docs/repair/ws-project-v3/optimized-results/cross-browser-en-US.log @@ -0,0 +1 @@ +PASS Chrome en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/optimized-results/cross-browser-zh-CN.json b/docs/repair/ws-project-v3/optimized-results/cross-browser-zh-CN.json new file mode 100644 index 0000000..c68e2d7 --- /dev/null +++ b/docs/repair/ws-project-v3/optimized-results/cross-browser-zh-CN.json @@ -0,0 +1,714 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "state": 0, + "writes": 1, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 5, + "writes": 3, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "state": 0, + "writes": 3, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/optimized-results/cross-browser-zh-CN.log b/docs/repair/ws-project-v3/optimized-results/cross-browser-zh-CN.log new file mode 100644 index 0000000..e4df6f9 --- /dev/null +++ b/docs/repair/ws-project-v3/optimized-results/cross-browser-zh-CN.log @@ -0,0 +1 @@ +PASS Chrome zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/publication-control.txt b/docs/repair/ws-project-v3/publication-control.txt new file mode 100644 index 0000000..4a2046f --- /dev/null +++ b/docs/repair/ws-project-v3/publication-control.txt @@ -0,0 +1,5 @@ +PASS actual WS controls: all four foreign controls rejected, owner controls work; borrowed original pinned, fd/epoch/server reuse and late close isolated; owner stop drains +PASS accepted cancellation persists through task/key/create/connect/auth; cancel/submit claim both orders and result freeze tested; duplicate/old/zero IDs isolated +PASS USER/TIMEOUT/MATCH keep distinct results; service stop busy does not cancel business, accepted user intent survives stop retry and all resource ledgers drain +PASS output failure seals observation without cancelling business; later explicit cancel still reaches original executor without rewriting terminal; earlier timeout retains reason +PASS actual ssh.cancel API exact-ID validation and accepted-intent response; ended operations reject without wildcard control diff --git a/docs/repair/ws-project-v3/publication-cross.txt b/docs/repair/ws-project-v3/publication-cross.txt new file mode 100644 index 0000000..8f47257 --- /dev/null +++ b/docs/repair/ws-project-v3/publication-cross.txt @@ -0,0 +1 @@ +PASS Node en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/publication-gate.md b/docs/repair/ws-project-v3/publication-gate.md new file mode 100644 index 0000000..b417061 --- /dev/null +++ b/docs/repair/ws-project-v3/publication-gate.md @@ -0,0 +1,16 @@ +# v3 提交前独立审查 + +结论:可以推送,范围限已验证的本地修改。用户在实施交付后明确授权更新 PR #42。 + +当前基线与 PR head 同为 568b871,原 Fork 分支 fix/v0.5.2-reliability-and-prompts。以追加提交更新,不重写历史,不合并或发布。 + +审查依据:最终 runtime diff、实际下层 EOF/释放、四控制入口、请求/终态分类、JS 消费及后续输入、冻结反例、完整验证记录。843 项最终输入哈希无变化;v2 controller、TX 与采集预算保持。未发现本轮明确的阻断问题。 + +本次提交前重新执行: +- run_shell_driver.sh:真实驱动 EOF、部分写、EAGAIN、CLI 原输入回调、资源释放和停止重试通过(publication-shell.txt)。 +- node tests/prompts/project-cross.cjs:真实最终 C 字节经生产 JS,再进入下一次 C 请求通过(publication-cross.txt)。 +- run_control.sh:原 peer/ID 归属、取消各阶段、原因区分和停止交错通过(publication-control.txt)。 + +同一输入哈希的完整主机套件、中英文 Chrome、构建后消费者及 ESP-IDF v5.5.2 独立目录编译保留实施阶段证据,本次没有重复完整编译和所有浏览器测试。证据快照与 patch 保留历史空格;源码及测试差异单独做 whitespace 检查。 + +无关 output/、tmp/ 与 runtime-repair 未跟踪文件排除;不修改版本、发布工作流、硬件保护及匹配规则。真实设备、双核调度和网络性能仍未验收;完整 peer 不解决同连接缺少操作 ID;发送成功不是浏览器 ACK。新增 C 回归尚未接入 CI,远端只能据新 head 的实际检查报告状态。 diff --git a/docs/repair/ws-project-v3/publication-shell.txt b/docs/repair/ws-project-v3/publication-shell.txt new file mode 100644 index 0000000..b96e08c --- /dev/null +++ b/docs/repair/ws-project-v3/publication-shell.txt @@ -0,0 +1,6 @@ +PASS real Shell+client: zero data is not EOF; EOF then close releases wrapper/channel/session/socket; close callback exactly once +PASS real Shell+client: fatal write/timeout retires channel; persistent close EAGAIN falls back to local session teardown without waiting +PASS real Shell+client: partial initialization/open/PTY/shell-start failure and bounded EAGAIN all release owned resources +PASS Shell run: local exit requested by input callback stops before another network read; close still owns cleanup +PASS actual WebUI cleanup twice uses cleared handles; original operation/ticket/target and actual lower resources drain +PASS real lower resources survive stop timeout; accepted output and terminal drain on retry with no new business message diff --git a/docs/repair/ws-project-v3/registries.txt b/docs/repair/ws-project-v3/registries.txt new file mode 100644 index 0000000..eef5301 --- /dev/null +++ b/docs/repair/ws-project-v3/registries.txt @@ -0,0 +1,68 @@ +main/ts_services.c:627: esp_err_t ret = ts_api_register_all(); +main/ts_services.c:1032: .name = "hal", +main/ts_services.c:1044: .name = "storage", +main/ts_services.c:1056: .name = "led", +main/ts_services.c:1068: .name = "drivers", +main/ts_services.c:1080: .name = "power", +main/ts_services.c:1092: .name = "network", +main/ts_services.c:1104: .name = "security", +main/ts_services.c:1116: .name = "api", +main/ts_services.c:1128: .name = "https", +main/ts_services.c:1140: .name = "webui", +main/ts_services.c:1152: .name = "console", +main/ts_services.c:1164: .name = "automation", +main/ts_services.c:1186: ret = ts_service_register(&s_hal_service_def, &s_hal_handle); +main/ts_services.c:1194: ret = ts_service_register(&s_storage_service_def, &s_storage_handle); +main/ts_services.c:1202: ret = ts_service_register(&s_led_service_def, &s_led_handle); +main/ts_services.c:1210: ret = ts_service_register(&s_drivers_service_def, &s_drivers_handle); +main/ts_services.c:1218: ret = ts_service_register(&s_power_service_def, &s_power_handle); +main/ts_services.c:1226: ret = ts_service_register(&s_network_service_def, &s_network_handle); +main/ts_services.c:1234: ret = ts_service_register(&s_security_service_def, &s_security_handle); +main/ts_services.c:1242: ret = ts_service_register(&s_api_service_def, &s_api_handle); +main/ts_services.c:1250: ret = ts_service_register(&s_https_service_def, &s_https_handle); +main/ts_services.c:1258: ret = ts_service_register(&s_webui_service_def, &s_webui_handle); +main/ts_services.c:1266: ret = ts_service_register(&s_console_service_def, &s_console_handle); +main/ts_services.c:1274: ret = ts_service_register(&s_automation_service_def, &s_automation_handle); +components/ts_webui/src/ts_webui_ws.c:990: .uri = "/ws", +components/ts_api/src/ts_api_ssh.c:2415: .name = "ssh.exec", +components/ts_api/src/ts_api_ssh.c:2422: .name = "ssh.exec_stream", +components/ts_api/src/ts_api_ssh.c:2429: .name = "ssh.cancel", +components/ts_api/src/ts_api_ssh.c:2436: .name = "ssh.test", +components/ts_api/src/ts_api_ssh.c:2443: .name = "ssh.copyid", +components/ts_api/src/ts_api_ssh.c:2450: .name = "ssh.revoke", +components/ts_api/src/ts_api_ssh.c:2457: .name = "ssh.keygen", +components/ts_api/src/ts_api_ssh.c:2465: .name = "ssh.hosts.list", +components/ts_api/src/ts_api_ssh.c:2472: .name = "ssh.hosts.add", +components/ts_api/src/ts_api_ssh.c:2479: .name = "ssh.hosts.remove", +components/ts_api/src/ts_api_ssh.c:2486: .name = "ssh.hosts.get", +components/ts_api/src/ts_api_ssh.c:2493: .name = "ssh.hosts.export", +components/ts_api/src/ts_api_ssh.c:2500: .name = "ssh.hosts.import", +components/ts_api/src/ts_api_ssh.c:2508: .name = "ssh.commands.list", +components/ts_api/src/ts_api_ssh.c:2515: .name = "ssh.commands.add", +components/ts_api/src/ts_api_ssh.c:2522: .name = "ssh.commands.remove", +components/ts_api/src/ts_api_ssh.c:2529: .name = "ssh.commands.get", +components/ts_api/src/ts_api_ssh.c:2536: .name = "ssh.commands.export", +components/ts_api/src/ts_api_ssh.c:2543: .name = "ssh.commands.import", +components/ts_api/src/ts_api_ssh.c:2554: return ts_api_register_multiple(ssh_endpoints, +components/ts_webui/web/js/app.js:175: router.register('/', loadSystemPage); +components/ts_webui/web/js/app.js:176: router.register('/system', loadSystemPage); +components/ts_webui/web/js/app.js:177: router.register('/network', loadNetworkPage); +components/ts_webui/web/js/app.js:178: router.register('/ota', loadOtaPage); +components/ts_webui/web/js/app.js:179: router.register('/files', loadFilesPage); +components/ts_webui/web/js/app.js:181: router.register('/logs', () => { +components/ts_webui/web/js/app.js:189: router.register('/terminal', loadTerminalPage); +components/ts_webui/web/js/app.js:190: router.register('/commands', loadCommandsPage); +components/ts_webui/web/js/app.js:191: router.register('/security', loadSecurityPage); +components/ts_webui/web/js/app.js:192: router.register('/automation', loadAutomationPage); +components/ts_webui/web/js/app.js:2034: if (selectedName && !availableTempVars.find(v => v.name === selectedName)) { +components/ts_webui/web/js/app.js:2068: tempVarBindings[index].name = name; +components/ts_webui/web/js/app.js:2110: const varInfo = availableTempVars.find(v => v.name === b.name); +components/ts_webui/web/js/app.js:2431: let existing = availableTempVars.find(v => v.name === bv.name); +components/ts_webui/web/js/app.js:2870: if (result.data.devices.some(d => d.name === 'matrix' || d.layout === 'matrix')) { +components/ts_webui/web/js/app.js:5169: if (result.data.devices.some(d => d.name === 'matrix' || d.layout === 'matrix')) { +components/ts_webui/web/js/app.js:5202: const isMatrix = dev.name === 'matrix' || dev.layout === 'matrix'; +components/ts_webui/web/js/app.js:5430: const deviceData = window.ledDevicesCache?.find(d => d.name === device); +components/ts_webui/web/js/app.js:5514: const deviceData = window.ledDevicesCache?.find(d => d.name === device); +components/ts_webui/web/js/app.js:5976: const deviceData = window.ledDevicesCache?.find(d => d.name === device); +components/ts_webui/web/js/app.js:16116: const firmware = files.find(entry => entry.name === 'TianShanOS.bin') || +components/ts_webui/web/js/app.js:21061: params.uri = document.getElementById('source-ws-uri').value.trim(); diff --git a/docs/repair/ws-project-v3/results/adapter.log b/docs/repair/ws-project-v3/results/adapter.log new file mode 100644 index 0000000..7febc5e --- /dev/null +++ b/docs/repair/ws-project-v3/results/adapter.log @@ -0,0 +1,13 @@ +PASS G1 same observable assertion: old rejection callback cannot corrupt replacement Shell (whole production unit) +PASS G2 same observable assertion: pending A fails while B prepares; B settles before terminal, no output follows terminal +PASS B11 timer delete/barrier retry retains original params; busy stop recovers without new business; late timer cannot abort replacement +PASS bounded timer drain retry exhaustion is retained and explicitly resumed by stop retry +PASS B09 observation failure still executes actual matching and variable updates without aborting remote command +PASS original timeout and stop-on-match business abort semantics retained +PASS original cancel ID contract, user disconnecting status and frozen terminal recipient snapshot +PASS no recipients: no observation JSON/payload allocation; business executes and tickets retire +PASS task-create and allocation failure sweep: all actual contexts, credentials, output buffers and reservations reclaimed +PASS output encoding allocation sweep: no partial protocol objects escape, original ticket/resource ledgers drain +PASS healthy stop drains original Shell within bounded wait, worker self-stop rejected, timer barrier callback-before-return remains pinned +PASS timer allocation/start failure cleanup: no timer reference leak; underlying SSH deadline policy unchanged +PASS complete production WS unit: Shell output failure/close/startup failure, Exec task/callback/match/variables/timer cleanup and task-before-create-return; destroyed=84 diff --git a/docs/repair/ws-project-v3/results/browser.json b/docs/repair/ws-project-v3/results/browser.json new file mode 100644 index 0000000..a3ad5bd --- /dev/null +++ b/docs/repair/ws-project-v3/results/browser.json @@ -0,0 +1,31 @@ +[ + { + "name": "browser", + "command": [ + "npm", + "run", + "test:browser", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "name": "cross-browser-en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + }, + { + "name": "cross-browser-zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs", + "--browser" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ws-project-v3/results/browser.log b/docs/repair/ws-project-v3/results/browser.log new file mode 100644 index 0000000..a039eed --- /dev/null +++ b/docs/repair/ws-project-v3/results/browser.log @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (729.437291ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (272.524792ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (325.275125ms) +✔ en-US: initial language failure blocks controls and retry recovers (356.387875ms) +✔ delayed language package and rapid switches keep the latest requested language (275.792084ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (372.424292ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (289.534792ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (357.364958ms) +✔ initial delayed language keeps controls inert until the real package arrives (266.181584ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (349.318334ms) +✔ terminal can initialize after failed resource load using newly served resources (446.691125ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (679.726708ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (217.10475ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (193.948375ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (247.410375ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (289.153166ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (264.067041ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (203.259833ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (186.349208ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (225.070834ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (170.0385ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (184.442416ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (179.461334ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (248.38575ms) +✔ R3: late validation cannot revive an old apply entry en-US (259.659292ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (292.953208ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (381.539709ms) +✔ R6: fixed upload destination and separate refresh failure en-US (374.5865ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (342.098916ms) +✔ R2: authenticated startup initializes once (403.996458ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (290.781875ms) +✔ R4/R5: newest result wins over late success and late failure (306.662292ms) +✔ R3: overlapping writes to one path cannot claim current verified content (394.631792ms) +✔ R2: disposed page only removes its dashboard callback (316.358291ms) +✔ R2: stale finally cannot unlock the new page read (303.17125ms) +✔ R1: delayed sign-out does not clear a newer sign-in (357.729166ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (440.745167ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (461.678583ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 8605.612583 diff --git a/docs/repair/ws-project-v3/results/certificate.log b/docs/repair/ws-project-v3/results/certificate.log new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ws-project-v3/results/certificate.log @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ws-project-v3/results/control.log b/docs/repair/ws-project-v3/results/control.log new file mode 100644 index 0000000..4a2046f --- /dev/null +++ b/docs/repair/ws-project-v3/results/control.log @@ -0,0 +1,5 @@ +PASS actual WS controls: all four foreign controls rejected, owner controls work; borrowed original pinned, fd/epoch/server reuse and late close isolated; owner stop drains +PASS accepted cancellation persists through task/key/create/connect/auth; cancel/submit claim both orders and result freeze tested; duplicate/old/zero IDs isolated +PASS USER/TIMEOUT/MATCH keep distinct results; service stop busy does not cancel business, accepted user intent survives stop retry and all resource ledgers drain +PASS output failure seals observation without cancelling business; later explicit cancel still reaches original executor without rewriting terminal; earlier timeout retains reason +PASS actual ssh.cancel API exact-ID validation and accepted-intent response; ended operations reject without wildcard control diff --git a/docs/repair/ws-project-v3/results/cross-browser-en-US.json b/docs/repair/ws-project-v3/results/cross-browser-en-US.json new file mode 100644 index 0000000..c68e2d7 --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-browser-en-US.json @@ -0,0 +1,714 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "state": 0, + "writes": 1, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 5, + "writes": 3, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "state": 0, + "writes": 3, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/results/cross-browser-en-US.log b/docs/repair/ws-project-v3/results/cross-browser-en-US.log new file mode 100644 index 0000000..238358d --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-browser-en-US.log @@ -0,0 +1 @@ +PASS Chrome en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/results/cross-browser-zh-CN.json b/docs/repair/ws-project-v3/results/cross-browser-zh-CN.json new file mode 100644 index 0000000..c68e2d7 --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-browser-zh-CN.json @@ -0,0 +1,714 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "state": 0, + "writes": 1, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 5, + "writes": 3, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "state": 0, + "writes": 3, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/results/cross-browser-zh-CN.log b/docs/repair/ws-project-v3/results/cross-browser-zh-CN.log new file mode 100644 index 0000000..e4df6f9 --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-browser-zh-CN.log @@ -0,0 +1 @@ +PASS Chrome zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/results/cross-node-en-US.json b/docs/repair/ws-project-v3/results/cross-node-en-US.json new file mode 100644 index 0000000..c68e2d7 --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-node-en-US.json @@ -0,0 +1,714 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "state": 0, + "writes": 1, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 5, + "writes": 3, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "state": 0, + "writes": 3, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/results/cross-node-en-US.log b/docs/repair/ws-project-v3/results/cross-node-en-US.log new file mode 100644 index 0000000..8f47257 --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-node-en-US.log @@ -0,0 +1 @@ +PASS Node en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/results/cross-node-zh-CN.json b/docs/repair/ws-project-v3/results/cross-node-zh-CN.json new file mode 100644 index 0000000..c68e2d7 --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-node-zh-CN.json @@ -0,0 +1,714 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "state": 2, + "writes": 1, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "state": 2, + "writes": 1, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "state": 0, + "writes": 1, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "state": 0, + "writes": 1, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 0, + "writes": 1, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 1, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "state": 5, + "writes": 3, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "state": 0, + "writes": 3, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/results/cross-node-zh-CN.log b/docs/repair/ws-project-v3/results/cross-node-zh-CN.log new file mode 100644 index 0000000..9265d9e --- /dev/null +++ b/docs/repair/ws-project-v3/results/cross-node-zh-CN.log @@ -0,0 +1 @@ +PASS Node zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/ws-project-v3/results/f1_f2.log b/docs/repair/ws-project-v3/results/f1_f2.log new file mode 100644 index 0000000..854d7e5 --- /dev/null +++ b/docs/repair/ws-project-v3/results/f1_f2.log @@ -0,0 +1,23 @@ +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F2: protection transition survives ordinary log saturation +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS F1: actual Shell output immediate/deferred failure settles original operation; early callbacks remain safe +PASS original peer and operation identity isolation across reconnect +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS actual Exec callback: partial failure settles each target; observation closes while business collection continues without remote abort or replay +PASS protection queue recovery without new messages; partial socket failure never replays successful recipient +PASS separate ordinary slot/descriptor/byte exhaustion cannot consume power quota; power overload counted without construction +PASS persistent SDK rejection has bounded retry and observable terminal settlement +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ordinary class retained with completion; busy/timeout stop preserves output and protection progress +PASS ticks cannot evict transitions; four accepted transitions retain order, fifth overload is explicit +fair system.dashboard=25 +fair system.info=18 +fair system.memory=18 +fair system.cpu=24 +fair network.status=18 +fair power.status=18 +fair fan.status=18 +fair service.list=18 +PASS bounded sustained log/protection/topic competition: all eligible classes progress diff --git a/docs/repair/ws-project-v3/results/host.json b/docs/repair/ws-project-v3/results/host.json new file mode 100644 index 0000000..0454bdc --- /dev/null +++ b/docs/repair/ws-project-v3/results/host.json @@ -0,0 +1,108 @@ +[ + { + "name": "host", + "command": [ + "bash", + "tests/ws_subscriptions/run_host.sh" + ], + "exit": 0 + }, + { + "name": "operation", + "command": [ + "bash", + "tests/ws_subscriptions/run_operation.sh" + ], + "exit": 0 + }, + { + "name": "adapter", + "command": [ + "bash", + "tests/ws_subscriptions/run_operation_adapter.sh" + ], + "exit": 0 + }, + { + "name": "control", + "command": [ + "bash", + "tests/ws_subscriptions/run_control.sh" + ], + "exit": 0 + }, + { + "name": "reviewer", + "command": [ + "bash", + "tests/ws_subscriptions/run_reviewer.sh" + ], + "exit": 0 + }, + { + "name": "f1_f2", + "command": [ + "bash", + "tests/ws_subscriptions/run_f1_f2.sh" + ], + "exit": 0 + }, + { + "name": "runtime", + "command": [ + "bash", + "tests/runtime/run_all.sh" + ], + "exit": 0 + }, + { + "name": "certificate", + "command": [ + "bash", + "tests/certificate/run_host.sh" + ], + "exit": 0 + }, + { + "name": "prompts", + "command": [ + "npm", + "test", + "--prefix", + "tests/prompts" + ], + "exit": 0 + }, + { + "name": "release", + "command": [ + "python3", + "tests/release/test_release.py" + ], + "exit": 0 + }, + { + "name": "shell_driver", + "command": [ + "bash", + "tests/ws_subscriptions/run_shell_driver.sh" + ], + "exit": 0 + }, + { + "name": "cross-node-en-US", + "command": [ + "node", + "tests/prompts/project-cross.cjs" + ], + "exit": 0 + }, + { + "name": "cross-node-zh-CN", + "command": [ + "node", + "tests/prompts/project-cross.cjs" + ], + "exit": 0 + } +] \ No newline at end of file diff --git a/docs/repair/ws-project-v3/results/host.log b/docs/repair/ws-project-v3/results/host.log new file mode 100644 index 0000000..88ff604 --- /dev/null +++ b/docs/repair/ws-project-v3/results/host.log @@ -0,0 +1,23 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-project-v3/results/operation.log b/docs/repair/ws-project-v3/results/operation.log new file mode 100644 index 0000000..b6d8772 --- /dev/null +++ b/docs/repair/ws-project-v3/results/operation.log @@ -0,0 +1,2 @@ +PASS 16 failure schedules: encode/SDK/socket/stale peer, early/deferred done, duplicate tokens do not double-settle +PASS production operation/TX: 36 barrier schedules, ticket/target ledgers and B09 executor retention; destroyed=36 diff --git a/docs/repair/ws-project-v3/results/prompts.log b/docs/repair/ws-project-v3/results/prompts.log new file mode 100644 index 0000000..e2a9ba9 --- /dev/null +++ b/docs/repair/ws-project-v3/results/prompts.log @@ -0,0 +1,51 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (16.080917ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.232875ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (7.616708ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (4.855458ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.485167ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.611833ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (6.254041ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.957875ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.029167ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.411166ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (6.395291ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.465916ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.730709ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.393583ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.982583ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.160416ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.891917ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.927791ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.956458ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (6.10225ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.667792ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (7.6365ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (5.151833ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.21075ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.8295ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.818167ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (5.105292ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (5.5095ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.929792ms) +✔ en-US: upload and download aggregates cover all success and all failure (4.981292ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (4.549875ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.486417ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (5.076875ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.808708ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.602417ms) +✔ en-US: unknown stop result never escalates to forced termination (4.540833ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.71775ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.088375ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 255.165833 diff --git a/docs/repair/ws-project-v3/results/release.log b/docs/repair/ws-project-v3/results/release.log new file mode 100644 index 0000000..e76e6ef --- /dev/null +++ b/docs/repair/ws-project-v3/results/release.log @@ -0,0 +1,5 @@ +... +---------------------------------------------------------------------- +Ran 3 tests in 0.003s + +OK diff --git a/docs/repair/ws-project-v3/results/reviewer.log b/docs/repair/ws-project-v3/results/reviewer.log new file mode 100644 index 0000000..5a5cfbd --- /dev/null +++ b/docs/repair/ws-project-v3/results/reviewer.log @@ -0,0 +1,15 @@ +PASS R1/R4 real busy stop: existing task and full fanout continue with no new business message; retry succeeds +PASS HTTPD barrier timeout retains worker and retry state +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-project-v3/results/runtime.log b/docs/repair/ws-project-v3/results/runtime.log new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ws-project-v3/results/runtime.log @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ws-project-v3/results/shell_driver.log b/docs/repair/ws-project-v3/results/shell_driver.log new file mode 100644 index 0000000..b96e08c --- /dev/null +++ b/docs/repair/ws-project-v3/results/shell_driver.log @@ -0,0 +1,6 @@ +PASS real Shell+client: zero data is not EOF; EOF then close releases wrapper/channel/session/socket; close callback exactly once +PASS real Shell+client: fatal write/timeout retires channel; persistent close EAGAIN falls back to local session teardown without waiting +PASS real Shell+client: partial initialization/open/PTY/shell-start failure and bounded EAGAIN all release owned resources +PASS Shell run: local exit requested by input callback stops before another network read; close still owns cleanup +PASS actual WebUI cleanup twice uses cleared handles; original operation/ticket/target and actual lower resources drain +PASS real lower resources survive stop timeout; accepted output and terminal drain on retry with no new business message diff --git a/docs/repair/ws-project-v3/sdk-env.log b/docs/repair/ws-project-v3/sdk-env.log new file mode 100644 index 0000000..fb84a6a --- /dev/null +++ b/docs/repair/ws-project-v3/sdk-env.log @@ -0,0 +1,20 @@ +Checking "python3" ... +Python 3.12.4 +"python3" has been detected +Activating ESP-IDF 5.5 +Setting IDF_PATH to '/Users/massif/esp/v5.5.2/esp-idf'. +* Checking python version ... 3.12.4 +* Checking python dependencies ... OK +* Deactivating the current ESP-IDF environment (if any) ... OK +* Establishing a new ESP-IDF environment ... OK +* Identifying shell ... zsh +* Detecting outdated tools in system ... Found tools that are not used by active ESP-IDF version. +For removing old versions of riscv32-esp-elf, cmake, xtensa-esp-elf, openocd-esp32, esp-rom-elfs, xtensa-esp-elf-gdb, riscv32-esp-elf-gdb use command 'python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall' +To free up even more space, remove installation packages of those tools. +Use option python /Users/massif/esp/v5.5.2/esp-idf/tools/idf_tools.py uninstall --remove-archives. +* Shell completion ... Autocompletion code generated + +Done! You can now compile ESP-IDF projects. +Go to the project directory and run: + + idf.py build diff --git a/docs/repair/ws-project-v3/target-resource.json b/docs/repair/ws-project-v3/target-resource.json new file mode 100644 index 0000000..081f751 --- /dev/null +++ b/docs/repair/ws-project-v3/target-resource.json @@ -0,0 +1,522 @@ +{ + "components/ts_security/src/ts_ssh_shell.c": { + "before": { + "object_bytes": 1076, + "stack_usage": { + "get_term_string": [ + "32", + "static" + ], + "wait_socket": [ + "64", + "static" + ], + "ts_ssh_shell_open": [ + "80", + "static" + ], + "ts_ssh_shell_close": [ + "32", + "static" + ], + "ts_ssh_shell_write": [ + "48", + "static" + ], + "ts_ssh_shell_read": [ + "32", + "static" + ], + "ts_ssh_shell_set_output_cb": [ + "32", + "static" + ], + "ts_ssh_shell_set_close_cb": [ + "32", + "static" + ], + "ts_ssh_shell_poll": [ + "32", + "static" + ], + "ts_ssh_shell_run": [ + "64", + "static" + ], + "ts_ssh_shell_resize": [ + "48", + "static" + ], + "ts_ssh_shell_send_signal": [ + "32", + "static" + ], + "ts_ssh_shell_get_state": [ + "32", + "static" + ], + "ts_ssh_shell_is_active": [ + "32", + "static" + ], + "ts_ssh_shell_get_exit_code": [ + "32", + "static" + ] + } + }, + "after": { + "object_bytes": 1080, + "stack_usage": { + "get_term_string": [ + "32", + "static" + ], + "shell_notify_close": [ + "32", + "static" + ], + "wait_socket": [ + "64", + "static" + ], + "shell_wait": [ + "32", + "static" + ], + "shell_release_channel": [ + "32", + "static" + ], + "ts_ssh_shell_open": [ + "96", + "static" + ], + "ts_ssh_shell_request_close": [ + "32", + "static" + ], + "ts_ssh_shell_close": [ + "32", + "static" + ], + "ts_ssh_shell_write": [ + "48", + "static" + ], + "ts_ssh_shell_read": [ + "32", + "static" + ], + "ts_ssh_shell_set_output_cb": [ + "32", + "static" + ], + "ts_ssh_shell_set_close_cb": [ + "32", + "static" + ], + "ts_ssh_shell_poll": [ + "48", + "static" + ], + "ts_ssh_shell_run": [ + "64", + "static" + ], + "ts_ssh_shell_resize": [ + "64", + "static" + ], + "ts_ssh_shell_send_signal": [ + "32", + "static" + ], + "ts_ssh_shell_get_state": [ + "32", + "static" + ], + "ts_ssh_shell_is_active": [ + "32", + "static" + ], + "ts_ssh_shell_get_exit_code": [ + "32", + "static" + ] + } + } + }, + "components/ts_webui/src/ts_webui_ws.c": { + "before": { + "object_bytes": 20, + "stack_usage": { + "power_state_to_string": [ + "32", + "static" + ], + "has_log_clients": [ + "32", + "static" + ], + "power_policy_event_handler": [ + "736", + "static" + ], + "ssh_request_error": [ + "48", + "static" + ], + "add_client": [ + "96", + "static" + ], + "terminal_output_cb": [ + "32", + "static" + ], + "handle_terminal_command": [ + "64", + "static" + ], + "ssh_send_output": [ + "320", + "static" + ], + "shell_destroy": [ + "32", + "static" + ], + "exec_destroy": [ + "32", + "static" + ], + "ssh_start_status": [ + "80", + "static" + ], + "ssh_close": [ + "32", + "static" + ], + "ssh_disconnecting": [ + "320", + "static" + ], + "shell_resources_close": [ + "32", + "static" + ], + "ssh_poll_task": [ + "2096", + "static" + ], + "handle_ssh_control": [ + "64", + "static" + ], + "exec_timer_drained": [ + "32", + "static" + ], + "exec_retry_timer_drain": [ + "48", + "static" + ], + "ssh_cleanup": [ + "32", + "static" + ], + "ts_webui_ws_stopped": [ + "32", + "static" + ], + "log_ws_callback": [ + "48", + "static" + ], + "exec_abort": [ + "32", + "static" + ], + "ssh_exec_timeout_callback": [ + "32", + "static" + ], + "simple_pattern_match": [ + "48", + "static" + ], + "ssh_exec_task": [ + "544", + "static" + ], + "ssh_exec_output_callback": [ + "1088", + "static" + ], + "exec_maintenance": [ + "32", + "static" + ], + "ts_webui_ssh_exec_start_ex_impl": [ + "528", + "static" + ], + "ts_webui_ws_init": [ + "64", + "static" + ], + "ts_webui_broadcast": [ + "48", + "static" + ], + "ts_webui_broadcast_event": [ + "32", + "static" + ], + "ts_webui_log_stream_enable": [ + "32", + "static" + ], + "update_log_stream_state": [ + "32", + "static" + ], + "cleanup_disconnected_client": [ + "128", + "static" + ], + "peer_closed": [ + "64", + "static" + ], + "set_client_role": [ + "128", + "static" + ], + "start_terminal_session": [ + "128", + "static" + ], + "handle_ssh_connect": [ + "208", + "static" + ], + "ws_handler": [ + "176", + "static" + ], + "ts_webui_ws_stop": [ + "32", + "static" + ], + "ts_webui_ssh_exec_start_ex": [ + "144", + "static" + ], + "ts_webui_ssh_exec_start": [ + "48", + "static" + ], + "ts_webui_ssh_result_free": [ + "32", + "static" + ], + "ts_webui_ssh_exec_cancel": [ + "32", + "static" + ], + "ts_webui_ssh_exec_is_running": [ + "32", + "static" + ] + } + }, + "after": { + "object_bytes": 20, + "stack_usage": { + "power_state_to_string": [ + "32", + "static" + ], + "has_log_clients": [ + "32", + "static" + ], + "power_policy_event_handler": [ + "736", + "static" + ], + "ssh_request_error": [ + "48", + "static" + ], + "add_client": [ + "96", + "static" + ], + "terminal_output_cb": [ + "32", + "static" + ], + "handle_terminal_command": [ + "64", + "static" + ], + "ssh_send_output": [ + "320", + "static" + ], + "shell_destroy": [ + "32", + "static" + ], + "exec_destroy": [ + "32", + "static" + ], + "ssh_start_status": [ + "80", + "static" + ], + "ssh_close": [ + "32", + "static" + ], + "ssh_disconnecting": [ + "320", + "static" + ], + "shell_resources_close": [ + "32", + "static" + ], + "ssh_poll_task": [ + "2096", + "static" + ], + "handle_ssh_control": [ + "96", + "static" + ], + "exec_timer_drained": [ + "32", + "static" + ], + "exec_retry_timer_drain": [ + "48", + "static" + ], + "ssh_cleanup": [ + "32", + "static" + ], + "ts_webui_ws_stopped": [ + "32", + "static" + ], + "log_ws_callback": [ + "48", + "static" + ], + "exec_abort": [ + "32", + "static" + ], + "ssh_exec_timeout_callback": [ + "32", + "static" + ], + "simple_pattern_match": [ + "48", + "static" + ], + "ssh_exec_task": [ + "544", + "static" + ], + "ssh_exec_output_callback": [ + "1088", + "static" + ], + "exec_maintenance": [ + "32", + "static" + ], + "ts_webui_ssh_exec_start_ex_impl": [ + "528", + "static" + ], + "ts_webui_ws_init": [ + "64", + "static" + ], + "ts_webui_broadcast": [ + "48", + "static" + ], + "ts_webui_broadcast_event": [ + "32", + "static" + ], + "ts_webui_log_stream_enable": [ + "32", + "static" + ], + "update_log_stream_state": [ + "32", + "static" + ], + "cleanup_disconnected_client": [ + "128", + "static" + ], + "peer_closed": [ + "64", + "static" + ], + "set_client_role": [ + "128", + "static" + ], + "start_terminal_session": [ + "128", + "static" + ], + "handle_ssh_connect": [ + "208", + "static" + ], + "ws_handler": [ + "176", + "static" + ], + "ts_webui_ws_stop": [ + "32", + "static" + ], + "ts_webui_ssh_exec_start_ex": [ + "144", + "static" + ], + "ts_webui_ssh_exec_start": [ + "48", + "static" + ], + "ts_webui_ssh_result_free": [ + "32", + "static" + ], + "ts_webui_ssh_exec_cancel": [ + "32", + "static" + ], + "ts_webui_ssh_exec_is_running": [ + "32", + "static" + ] + } + } + } +} \ No newline at end of file diff --git a/docs/repair/ws-project-v3/working-tree-status.txt b/docs/repair/ws-project-v3/working-tree-status.txt new file mode 100644 index 0000000..0e1125d --- /dev/null +++ b/docs/repair/ws-project-v3/working-tree-status.txt @@ -0,0 +1,25 @@ + M components/ts_console/commands/ts_cmd_ssh.c + M components/ts_security/include/ts_ssh_shell.h + M components/ts_security/src/ts_ssh_shell.c + M components/ts_webui/src/ts_webui_ws.c + M components/ts_webui/web/index.html + M components/ts_webui/web/js/lang/en-US.js + M components/ts_webui/web/js/lang/zh-CN.js + M components/ts_webui/web/js/terminal.js + M docs/repair/ws-control/README.md + M tests/ws_subscriptions/test_operation_adapter.c +?? docs/repair/ws-project-v3/ +?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt +?? output/ +?? tests/prompts/project-cross.cjs +?? tests/ws_subscriptions/measure_project_v3.py +?? tests/ws_subscriptions/project_driver.inc +?? tests/ws_subscriptions/project_stubs/ +?? tests/ws_subscriptions/replay_project_baseline.py +?? tests/ws_subscriptions/run_project_bridge.sh +?? tests/ws_subscriptions/run_project_v3.py +?? tests/ws_subscriptions/run_shell_driver.sh +?? tests/ws_subscriptions/test_project.c +?? tests/ws_subscriptions/test_shell_driver.c +?? tests/ws_subscriptions/verify_project_assets.py +?? tmp/ diff --git a/docs/repair/ws-subscriptions/README.md b/docs/repair/ws-subscriptions/README.md new file mode 100644 index 0000000..e0107fe --- /dev/null +++ b/docs/repair/ws-subscriptions/README.md @@ -0,0 +1,116 @@ +> 后续 Reviewer 确认 R1—R5 后的修复、冻结基线与验收边界,以 [reviewer-fixes/README.md](reviewer-fixes/README.md) 为准;下文保留首次实施记录。 + +# WebSocket 设备端开销与生命周期修复记录 + +日期:2026-09-24。基线:`35238b4645ae5e9e0e99555d4fb64080d945565c`;分支 `fix/v0.5.2-reliability-and-prompts`;SDK:本地 ESP-IDF **v5.5.2**。本记录针对当前未提交 diff,不是设备验收或发布许可。 + +原有未跟踪的 `output/`、`tmp/`、`docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt` 保留。没有回退、提交、推送、更新 PR、修改版本/发布工作流、连接设备、刷机、重启或执行远端命令。附带文档作为设计依据;按当前代码作出的调整列在下文。 + +## 处理状态 + +| 问题 | 结果及实际修改 | +|---|---| +| P1 无订阅仍采集 | 移除三个展示用 esp_timer。单一 `ws_telemetry` 任务按截止时间/通知等待;没有周期需求时不轮询。最后订阅失效后不再启动其 API 读取;当前不可中断 API 允许收尾。 | +| P2 未到期仍采集、组包 | 在 API 前选出到期、无 pending、有容量的目标;空集合不分配 JSON。dashboard 与单主题按同批指标并集读取。间隔基于实际发送完成推进,失败单独退避。 | +| P3 主题循环全体广播 | 主题只提交身份固定的目标。每个主题每批序列化一次;每个目标一次。真正全局告警仍取全部有效连接快照。 | +| D1 真实停止缺失 | WebUI stop/deinit、HTTP 独立 stop/deinit、启动失败回滚接入停止 hook;失败向上传递,保留句柄和 STOPPING,允许重试。 | +| D2 API 结果泄漏 | 每次 API 使用独立结果对象;转移 data 后置空,所有分支调用 `ts_api_result_free()`,包括业务失败和错误 message。 | +| D3 事件节点提前释放 | 有上限的处理器快照持有节点引用;注销先退休节点,不再开始新回调。同步注销等待 in-flight,超时保留句柄供重试。自注销不等待自己。事件总线 deinit 改为协作等待,不强删正在执行回调的任务。 | +| D4 共享 handler / system.info | 统一调度八个周期主题。三个事件 handler 随管理器注册/排空,不再由某个系统主题单独注销共享 handler;system.info 可独立到期采集。 | +| 新增 A1:SDK cJSON 引用辅助函数失败泄漏 | 分配失败扫描发现 `cJSON_AddItemReferenceToObject` 的临时引用在键分配失败时丢失。改为显式持有引用节点、常量键添加及失败回收;不复制一棵长期存活的数据树。 | +| 新增 A2:HTTPD 控制邮箱容量 | 当前 `CONFIG_LWIP_UDP_RECVMBOX_SIZE=6`,queue_work 使用本地 UDP,不能把几十个描述符直接塞入 SDK 邮箱。模块固定 FIFO 保存待发项,每次仅一个 TX work 在 HTTPD 中;完成只唤醒 worker,由 worker 推进下一条。停止屏障另占最多一个 work。未更改 SDK 或全局配置。 | +| 新增 A3:排空 TX 不代表 HTTP 请求结束 | 单独的 HTTPD 请求边界屏障;确认当前请求返回后才清理 SSH 资源。它不代替实际 outstanding 计数。 | +| 新增 A4:既有后台发送者越过服务器停止 | 全局、日志、SSH 输出接入受控发送归属。SSH 输出保存原连接身份;轮询任务退出前不释放会话;SSH 执行创建入口增加停止准入计数。进行中的执行不重放、不强制取消,停止返回 busy,正常结束后可重试。 | + +另外核对了 HTTPD URI 的所有权:SDK 不释放应用注册时分配的 route `user_ctx`。现在由 HTTP 包装器登记其副本,只在 **httpd_stop 成功以后**释放;失败保留。此项是重复启停回归的 I08/T29 依赖,不改变路由、认证或业务处理。 + +## 文件及实现边界 + +- `components/ts_webui/src/ts_ws_subscriptions.c`:需求调度、订阅 revision / delivery、独立间隔、指标共享、事件 FIFO、结果释放、稳定控制状态、协作停止。 +- 新增 `components/ts_webui/src/ts_ws_transport.c` / `include/ts_ws_transport.h`:完整 peer 身份、session free hook、有界消息/发送池、HTTPD 上下文最终验证、固定 FIFO、控制邮箱限流、失败 shutdown、统计和停止屏障。新增文件仅服务 WebUI,不是通用消息框架。 +- `ts_webui_ws.c`:握手登记、所有真实断线入口、旧会话拒绝、日志过滤、后台发送适配、初始化失败传播。停止时不释放仍在使用的 SSH 对象。 +- `ts_webui.c`、`ts_http_server.c/.h`:实际拥有者停止链、错误传播、HTTPD 自等待拒绝、停止中拒绝再次启动。 +- `ts_event.c/.h`:节点保活、退休、同步 drain、自注销/并发注销、等待者引用;未更改优先级、事件队列投递规则和其他模块的订阅集合。 +- `tests/ws_subscriptions/`、`tests/prompts/ownership.browser.test.cjs`:生产 C 回归与实际页面类兼容性测试。 + +## 按当前代码调整的设计 + +1. 当前只有 HTTP `/ws`,HTTPS 没有独立 WebSocket 注册。传输管理器明确只接纳一个 HTTPD 实例;第二个实例返回错误,未新增 HTTPS WS。仍使用 server epoch 隔离相同 handle 地址重用。 +2. 当前 `/ws` 没有独立认证/主题授权检查。没有把 active 或订阅当作鉴权,也没有宣称补好了认证。新增目标检查收窄了原来的广播范围;会话有效性、订阅身份和日志过滤在执行时重验。**认证/授权撤销的端到端安全验收不适用当前实现,仍是独立安全缺口。** +3. session context 为空时才安装 free hook;已有 context 时拒绝接入,不覆盖 TLS/认证上下文。正常 close、RST、LRU、HTTPD stop 都归于 SDK session free 流程。发送失败在 HTTPD 所有者上下文对已验证的 fd 执行 shutdown,实际 close 仍归 SDK。 +4. 原来 add_client 的“探测/抢占”只移除应用表项,没有结束真实会话;现改为容量不足明确拒绝登记,由 SDK 结束失败请求。原唯一调用位置是普通事件握手;其中按 terminal/SSH 类型抢占的分支在该入口并不会触发。 +5. 周期 interval 最小为 dashboard/CPU 1 秒,其余 5 秒;更长 interval 真正减少读取。当前 dashboard 页面请求 1000 ms,与之兼容。新订阅首帧在一个有效间隔内;相同参数重复订阅不重置进度。事件默认 interval 0 的既有语义保留。 +6. device/OTA/config 操作事件用有界 FIFO 保留顺序,不做 latest-only;满载/过大/分配失败会计数或返回提交失败,不伪造送达,也不改变原 HTTP 操作结果。 +7. 全局/流式发送使用独立描述符配额;不覆盖旧日志/SSH 数据。有限容量仍可能拒绝过载流,拒绝计数可见;没有引入端到端可靠投递协议。 +8. 已有终端缓冲及互斥锁保留为可重用单例,不在可能存在历史 console callback 时销毁;不会每次重启新建一套。未把本轮适配称为全部终端/SSH/日志代码的完整审计。 + +## 锁、所有权和停止 + +| 对象 | 所有者 / 同步 | 回收条件 | +|---|---|---| +| manager 控制状态 | 永久静态短临界区;入口计数 | 不释放临界区;实例状态只在 producer、worker、delivery 全部排空后回到 OFF | +| 订阅 / revision / pending | manager 锁内改值;worker 仅复制值快照 | 旧完成必须同时匹配 revision 和 delivery;不能回写新订阅 | +| peer | transport 短锁;HTTPD 创建、删除、最终发送 | server handle + epoch + fd + connection 同时匹配;旧 hook 不清理新会话 | +| API data | 本轮 worker | data 转移后原指针置空;结果和 error message 每次释放 | +| message | 固定槽引用计数;不可变字符串共享 | 最后拥有者释放;实际 free 完成前仍保留槽和字节配额 | +| TX descriptor | 固定池,PREPARED/QUEUED/EXECUTING/DONE/CANCELED | 准备/发布/执行各自的引用明确;回调早于 queue_work 返回也不会复用或二次释放 | +| handler node | 总线互斥锁;快照、调用、等待者 pin | 已退休且所有引用归零;超时 drain 保留供重试 | +| handler user_data | manager / 调用方 | 同步 unregister 成功或 NOT_FOUND 后才允许释放;本模块使用固定 topic 值上下文 | + +没有在订阅锁/连接锁内调用 API、JSON、网络、queue_work 或等待 drain。HTTPD 最终校验与会话创建/删除在同一所有者上下文;已经进入传输的帧不能撤回。 + +停止顺序:关闭 WebUI 新准入 → manager STOPPING/失效订阅 → 同步排空自己的事件 handler → worker 收尾/取消未提交主题任务/等待真实 delivery → HTTPD 请求边界 → 排空 power handler、检查 SSH 创建/执行和协作轮询退出 → transport 停止准入、取消未提交项、等待已提交工作 → 真正 httpd_stop → 释放实例身份。任一步失败保留安全状态;不会超时强制 free。 + +全事件总线销毁仍依赖系统服务拥有者先停止外部事件发布者。本轮验证的是节点/回调/drain,不声称审计了所有第三方生产者与整个系统关机顺序。 + +## 测试与证据 + +[基线](evidence/baseline.json)、[旧版红灯](evidence/baseline-red.txt)、[生产 C 主机回归](evidence/host.txt)、[额外分配失败发现](evidence/allocation-finding.txt)。 + +| 命令 | 结果 / 证据边界 | +|---|---| +| `./tests/ws_subscriptions/run_baseline.sh` | 脚本退出 0 表示确认了预期失败:T02 无订阅仍 7 次 API;T05 未到期仍 7 次;T07 两次全体广播。原 dispatcher 的自注销触发 ASan heap-use-after-free。不是编译错误冒充红灯。 | +| `./tests/ws_subscriptions/run_host.sh` | ASan/UBSan;完整生产 manager、transport、SDK cJSON、event C;实际停止及初始化函数体。测试边界和方式见 tests README。 | +| 事件测试 `-fsanitize=thread` | 当前 pthread 事件测试通过;不代表模拟 FreeRTOS 调度器或全固件通过 TSan。见 [记录](evidence/tsan.txt)。 | +| `./tests/runtime/run_all.sh` | 原有运行时回归通过,[记录](evidence/runtime.txt)。 | +| `./tests/certificate/run_host.sh` | 原有证书/HTTPS/停止回归通过,[记录](evidence/certificate.txt)。其中 REPRODUCED 是该测试的旧版反例,不是当前失败。 | +| `npm ci --prefix tests/prompts --cache /tmp/tianshan-pr-npm-cache`、`npm test --prefix tests/prompts` | 38 项通过;未修改依赖锁文件,[记录](evidence/prompts.txt)。 | +| `npm run test:browser --prefix tests/prompts` | 本地 Chrome,38 项通过;新增中英文双页面、不同 interval、订阅/取消确认及取消后不回调;保留 R1—R6 切页回归,[记录](evidence/browser.txt)。WebSocket/设备响应模拟,不是实板网络。 | +| `git diff --check` | 通过。 | +| 独立 ESP-IDF 编译 | 见 [构建与资源记录](evidence/build.txt)。原 `build/*.bin` 未覆盖。 | + +### 交接矩阵映射 + +“主机通过”只表示对应生产函数在可控边界下的断言成立;设备项没有执行。 + +| ID | 结果 | +|---|---| +| T01—T03 | 无需求/取消后计数停止、恢复、重订交错;主机通过。 | +| T04 | 发送失败、session free、幂等身份清理通过;实际 RST/LRU/close 的 SDK 接入经源码核对,实网未执行。 | +| T05—T10 | 到期前零读取、独立间隔、定向、不重复、参数代次、数值范围;主机通过。 | +| T11—T13 | 独立 system.info、共享批次、API 中取消跳过剩余指标;主机通过。 | +| T14—T16 | fd/handle 重用、旧完成不改新 pending;主机通过。第二同时服务器按当前单所有者契约拒绝。 | +| T17 | 分配/queue 失败、回调先于发布返回、单 SDK work、引用及退避;主机通过。实际 UDP 丢包未伪称已测试。 | +| T18 | 固定描述符/总字节、保留全局配额、最大帧边界、32 服务转义名称大小压力;主机通过。真实慢网络、完整设备最大组合负载需实机。 | +| T19—T22 | 延迟完成不追赶、统计层次、业务失败释放、179 个分配失败位置扫描与连续轮次回到分配基线;主机通过。 | +| T23—T25 | 连续操作结果顺序、借用数据复制、事件 FIFO 满载、非 NUL 事件、事件间隔、全局接收集合;主机通过。 | +| T26 | manager task/部分注册回滚;实际 WS 初始化的 server/transport/manager/两个锁/缓冲/URI/power handler 失败返回;主机通过。完整硬件驱动启动失败注入未执行。 | +| T27—T30 | API/queued work 中停止,HTTPD 屏障超时/重试,真实 stop 错误传播、重复生命周期、自等待拒绝;主机通过。 | +| T31 | 当前没有独立 WS 鉴权,不能宣称通过授权撤销测试;身份/未订阅隔离已测。 | +| T32 | pthread 屏障证明节点选中后注销、in-flight drain、自注销、超时重试、其他 handler 保留;ASan/UBSan/TSan 通过。 | +| T33—T34 | 等待边界通知、单调时间/向上取 tick/大值封顶及非零等待;主机通过,未测目标 RTOS 抢占和墙钟真实切换。 | + +额外执行四个边界 × 五类变更:快照后、API 中、SDK 工作待执行、send 返回/完成写回前,分别取消、重订、断线、fd 重用、停止并拒绝未排空重启。每次排空后重新初始化成功。不是仅检查“没有崩溃”,也断言目标帧数、API 次数、pending/时间归属和活跃分配归零。 + +## 资源预算与设备验收 + +- 单 worker:8192 字节栈、优先级 2、无绑核;SDK 静态 TCB 对应尺寸由目标编译测得 **352 字节**。实际栈水位字段已保留,未运行设备,因此没有实机水位数值。 +- 32 个订阅;4 个操作事件槽,事件消息计入同一有界字符串池。每订阅最多一条周期在途投递。 +- 当前 8 连接配置:32 个主题 TX 描述符 + 8 个全局/流式描述符;独立配额。内部 FIFO 不直接对应 SDK 邮箱项;每次最多 1 个 TX work + 1 个停止屏障进入 SDK。 +- 8 个消息槽,6 个供主题/事件、2 个供全局/流式,配额互不占用;遥测单帧上限 32768 字节,旧流式/全局文本单帧须小于 512 KiB;传输池拥有的消息字符串合计硬上限 1 MiB。不是预先常驻分配 1 MiB。过大明确拒绝,不截断。 +- 事件 FIFO 自身至多 4 × 32768 = 128 KiB 字符串,包含在总预算内。主题 JSON 用预分配上限缓冲区输出,不是先无限分配再量长度。 +- 当前 32 服务、31 字节全转义名称的尺寸压力样本为 9991 字节;512 KiB 旧流文本边界另测。这不是全部传感器真实最大组合负载的实板证明。 +- 静态对象尺寸由目标 object/nm 记录在 [资源记录](evidence/resources.txt)。临时 API cJSON / 系统 CPU API 的任务快照仍按既有 API 实现分配,以及既有全局/流式生产者的临时 JSON/string,不包含在 TX 字符串预算中。 +- 不预先宣称 CPU/功耗下降百分比或总 RAM 一定减少。显示采集次数减少已在主机计数验证;CPU、耗时分位、内部 RAM/PSRAM 峰值和长期堆变化必须实测。 + +需要另行授权的实机清单:无人订阅;一个 dashboard;10 秒间隔;多个快慢标签页与未订阅页;慢连接/断线/RST/LRU;反复切页重连与 fd 重用;最大服务/风扇/网络配置和长输出;事件连续完成及过载;有 SSH/日志输出时的 WebUI/HTTP 独立停止、失败重试及重新启动;观察栈水位、堆回归、发送耗时、计数和原全局电压告警。未执行刷机、这些操作或任何硬件保护测试。 diff --git a/docs/repair/ws-subscriptions/changes.patch b/docs/repair/ws-subscriptions/changes.patch new file mode 100644 index 0000000..52251e3 --- /dev/null +++ b/docs/repair/ws-subscriptions/changes.patch @@ -0,0 +1,3573 @@ +diff --git a/components/ts_core/ts_event/include/ts_event.h b/components/ts_core/ts_event/include/ts_event.h +index 23703dd..10f1505 100644 +--- a/components/ts_core/ts_event/include/ts_event.h ++++ b/components/ts_core/ts_event/include/ts_event.h +@@ -372,6 +372,12 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, + */ + esp_err_t ts_event_unregister(ts_event_handler_handle_t handle); + ++/** Stop new invocations and drain existing callbacks. Timeout retains the handle ++ * for retry; only ESP_OK / NOT_FOUND permits freeing user_data. Never call from ++ * an event callback (including post_sync); use nonblocking unregister there. */ ++esp_err_t ts_event_unregister_sync(ts_event_handler_handle_t handle, uint32_t timeout_ms); ++bool ts_event_in_callback(void); ++ + /** + * @brief 取消注册指定事件的所有处理器 + * +diff --git a/components/ts_core/ts_event/src/ts_event.c b/components/ts_core/ts_event/src/ts_event.c +index e80dee2..4dc94cf 100644 +--- a/components/ts_core/ts_event/src/ts_event.c ++++ b/components/ts_core/ts_event/src/ts_event.c +@@ -10,6 +10,7 @@ + + #include + #include ++#include + #include "ts_event.h" + #include "esp_log.h" + #include "esp_timer.h" +@@ -50,6 +51,10 @@ typedef struct ts_event_handler_instance { + ts_event_priority_t min_priority; + ts_event_handler_t handler; + void *user_data; ++ bool retired; ++ bool drain_pending; ++ unsigned refs; /* snapshots + synchronous unregister waiters */ ++ unsigned in_flight; + struct ts_event_handler_instance *next; + } ts_event_handler_instance_t; + +@@ -80,7 +85,7 @@ typedef struct { + ts_event_handler_instance_t *handlers; + size_t handler_count; + ts_event_stats_t stats; +- bool running; ++ atomic_bool running; + } ts_event_context_t; + + /* ============================================================================ +@@ -89,6 +94,14 @@ typedef struct { + + static ts_event_context_t s_event_ctx = {0}; + ++/* Includes synchronous posts from arbitrary tasks and nested dispatch. */ ++typedef struct dispatch_scope { ++ TaskHandle_t task; ++ struct dispatch_scope *next; ++} dispatch_scope_t; ++static dispatch_scope_t *s_dispatch_scopes; ++ ++ + /* ============================================================================ + * 私有函数声明 + * ========================================================================== */ +@@ -169,6 +182,7 @@ esp_err_t ts_event_deinit(void) + return ESP_ERR_INVALID_STATE; + } + ++ if (ts_event_in_callback()) return ESP_ERR_INVALID_STATE; + ESP_LOGI(TAG, "Deinitializing event system..."); + + // 停止事件循环 +@@ -178,17 +192,18 @@ esp_err_t ts_event_deinit(void) + ts_event_internal_t dummy = {0}; + xQueueSend(s_event_ctx.event_queue, &dummy, 0); + +- // 等待任务结束 +- vTaskDelay(pdMS_TO_TICKS(100)); +- +- // 删除任务 +- if (s_event_ctx.event_task != NULL) { +- vTaskDelete(s_event_ctx.event_task); +- s_event_ctx.event_task = NULL; ++ int64_t deadline = esp_timer_get_time() + 6000000; ++ for (;;) { ++ xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ++ bool draining = s_event_ctx.event_task || s_dispatch_scopes; ++ for (ts_event_handler_instance_t *p = s_event_ctx.handlers; p; p=p->next) ++ if (p->refs || p->drain_pending) draining = true; ++ if (!draining) break; /* retain lock for final free */ ++ xSemaphoreGive(s_event_ctx.mutex); ++ if (esp_timer_get_time() >= deadline) return ESP_ERR_TIMEOUT; ++ vTaskDelay(1); + } + +- xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); +- + // 释放所有处理器 + ts_event_handler_instance_t *handler = s_event_ctx.handlers; + while (handler != NULL) { +@@ -250,11 +265,6 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, + return ESP_ERR_INVALID_STATE; + } + +- if (s_event_ctx.handler_count >= TS_EVENT_HANDLERS_MAX) { +- ESP_LOGE(TAG, "Maximum handlers reached"); +- return ESP_ERR_NO_MEM; +- } +- + ts_event_handler_instance_t *node = TS_EVT_CALLOC(1, sizeof(ts_event_handler_instance_t)); + if (node == NULL) { + return ESP_ERR_NO_MEM; +@@ -268,6 +278,11 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, + + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + ++ if (!s_event_ctx.running || s_event_ctx.handler_count >= TS_EVENT_HANDLERS_MAX) { ++ xSemaphoreGive(s_event_ctx.mutex); ++ free(node); ++ return ESP_ERR_NO_MEM; ++ } + node->next = s_event_ctx.handlers; + s_event_ctx.handlers = node; + s_event_ctx.handler_count++; +@@ -285,78 +300,95 @@ esp_err_t ts_event_register_with_priority(ts_event_base_t event_base, + return ESP_OK; + } + +-esp_err_t ts_event_unregister(ts_event_handler_handle_t handle) ++/* Retired nodes remain discoverable while a drain waiter owns them. */ ++static void reclaim_handler(ts_event_handler_instance_t *node) + { +- if (handle == NULL) { +- return ESP_ERR_INVALID_ARG; +- } +- +- if (!s_event_ctx.initialized) { +- return ESP_ERR_INVALID_STATE; +- } ++ if (!node->retired || node->refs || node->drain_pending) return; ++ ts_event_handler_instance_t **link = &s_event_ctx.handlers; ++ while (*link && *link != node) link = &(*link)->next; ++ if (*link) { *link = node->next; free(node); } ++} + ++bool ts_event_in_callback(void) ++{ ++ if (!s_event_ctx.initialized) return false; ++ TaskHandle_t self = xTaskGetCurrentTaskHandle(); ++ bool found = false; + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ++ for (dispatch_scope_t *p = s_dispatch_scopes; p; p = p->next) ++ if (p->task == self) { found = true; break; } ++ xSemaphoreGive(s_event_ctx.mutex); ++ return found; ++} + +- ts_event_handler_instance_t *prev = NULL; ++static esp_err_t unregister_handler(ts_event_handler_handle_t handle, bool wait, ++ uint32_t timeout_ms) ++{ ++ if (!handle) return ESP_ERR_INVALID_ARG; ++ if (!s_event_ctx.initialized) return ESP_ERR_INVALID_STATE; ++ if (wait && ts_event_in_callback()) return ESP_ERR_INVALID_STATE; ++ xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + ts_event_handler_instance_t *node = s_event_ctx.handlers; +- ts_event_handler_instance_t *target = (ts_event_handler_instance_t *)handle; +- +- while (node != NULL) { +- if (node == target) { +- if (prev == NULL) { +- s_event_ctx.handlers = node->next; +- } else { +- prev->next = node->next; +- } +- s_event_ctx.handler_count--; +- s_event_ctx.stats.handlers_registered = s_event_ctx.handler_count; +- ++ while (node && node != handle) node = node->next; ++ if (!node) { xSemaphoreGive(s_event_ctx.mutex); return ESP_ERR_NOT_FOUND; } ++ if (!node->retired) { ++ node->retired = true; ++ s_event_ctx.handler_count--; ++ s_event_ctx.stats.handlers_registered = s_event_ctx.handler_count; ++ } ++ if (!wait) { ++ reclaim_handler(node); ++ xSemaphoreGive(s_event_ctx.mutex); ++ return ESP_OK; ++ } ++ node->drain_pending = true; ++ node->refs++; /* pins both node and its position while the lock is dropped */ ++ int64_t deadline = esp_timer_get_time() + (int64_t)timeout_ms * 1000; ++ while (node->in_flight) { ++ xSemaphoreGive(s_event_ctx.mutex); ++ vTaskDelay(1); ++ xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ++ if (node->in_flight && esp_timer_get_time() >= deadline) { ++ /* Keep a retired registry reference for retry, even after callbacks end. */ ++ node->refs--; + xSemaphoreGive(s_event_ctx.mutex); +- free(node); +- return ESP_OK; ++ return ESP_ERR_TIMEOUT; + } +- prev = node; +- node = node->next; + } +- ++ node->refs--; ++ node->drain_pending = false; ++ reclaim_handler(node); + xSemaphoreGive(s_event_ctx.mutex); +- return ESP_ERR_NOT_FOUND; ++ return ESP_OK; + } + +-esp_err_t ts_event_unregister_all(ts_event_base_t event_base, ts_event_id_t event_id) ++esp_err_t ts_event_unregister(ts_event_handler_handle_t handle) + { +- if (!s_event_ctx.initialized) { +- return ESP_ERR_INVALID_STATE; +- } ++ return unregister_handler(handle, false, 0); ++} + +- xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ++esp_err_t ts_event_unregister_sync(ts_event_handler_handle_t handle, uint32_t timeout_ms) ++{ ++ return unregister_handler(handle, true, timeout_ms); ++} + +- ts_event_handler_instance_t *prev = NULL; ++esp_err_t ts_event_unregister_all(ts_event_base_t base, ts_event_id_t id) ++{ ++ if (!s_event_ctx.initialized) return ESP_ERR_INVALID_STATE; ++ xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + ts_event_handler_instance_t *node = s_event_ctx.handlers; +- +- while (node != NULL) { +- bool match = (event_base == NULL || +- (node->base != NULL && strcmp(node->base, event_base) == 0)); +- if (match && (event_id == TS_EVENT_ANY_ID || node->id == event_id)) { +- ts_event_handler_instance_t *to_delete = node; +- if (prev == NULL) { +- s_event_ctx.handlers = node->next; +- node = s_event_ctx.handlers; +- } else { +- prev->next = node->next; +- node = node->next; +- } ++ while (node) { ++ ts_event_handler_instance_t *next = node->next; ++ if (!node->retired && (!base || (node->base && !strcmp(base, node->base))) && ++ (id == TS_EVENT_ANY_ID || id == node->id)) { ++ node->retired = true; + s_event_ctx.handler_count--; +- free(to_delete); +- } else { +- prev = node; +- node = node->next; ++ reclaim_handler(node); + } ++ node = next; + } +- + s_event_ctx.stats.handlers_registered = s_event_ctx.handler_count; + xSemaphoreGive(s_event_ctx.mutex); +- + return ESP_OK; + } + +@@ -659,6 +691,9 @@ static void event_loop_task(void *arg) + } + + ESP_LOGI(TAG, "Event loop task ended"); ++ xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ++ s_event_ctx.event_task = NULL; ++ xSemaphoreGive(s_event_ctx.mutex); + vTaskDelete(NULL); + } + +@@ -683,30 +718,41 @@ static void dispatch_event(const ts_event_internal_t *internal_event) + + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); + +- ts_event_handler_instance_t *handler = s_event_ctx.handlers; +- while (handler != NULL) { +- if (handler_matches(handler, internal_event)) { +- // 释放锁来调用处理器(避免死锁) ++ ts_event_handler_instance_t *snapshot[TS_EVENT_HANDLERS_MAX]; ++ size_t count = 0; ++ dispatch_scope_t scope = {.task = xTaskGetCurrentTaskHandle(), .next = s_dispatch_scopes}; ++ s_dispatch_scopes = &scope; ++ for (ts_event_handler_instance_t *p = s_event_ctx.handlers; p; p = p->next) { ++ if (!p->retired && handler_matches(p, internal_event)) { ++ p->refs++; ++ snapshot[count++] = p; ++ } ++ } ++ for (size_t i = 0; i < count; ++i) { ++ ts_event_handler_instance_t *p = snapshot[i]; ++ if (!p->retired) { ++ p->in_flight++; ++ ts_event_handler_t fn = p->handler; ++ void *data = p->user_data; + xSemaphoreGive(s_event_ctx.mutex); +- +- if (handler->handler != NULL) { +- handler->handler(&event, handler->user_data); +- } +- +- s_event_ctx.stats.events_delivered++; +- ++ fn(&event, data); + xSemaphoreTake(s_event_ctx.mutex, portMAX_DELAY); ++ p->in_flight--; ++ s_event_ctx.stats.events_delivered++; + } +- handler = handler->next; ++ p->refs--; ++ reclaim_handler(p); + } +- +- xSemaphoreGive(s_event_ctx.mutex); ++ dispatch_scope_t **link = &s_dispatch_scopes; ++ while (*link != &scope) link = &(*link)->next; ++ *link = scope.next; + + // 更新统计 + int64_t elapsed = esp_timer_get_time() - start_time; + if (elapsed > s_event_ctx.stats.max_delivery_time_us) { + s_event_ctx.stats.max_delivery_time_us = (uint32_t)elapsed; + } ++ xSemaphoreGive(s_event_ctx.mutex); + } + + static bool handler_matches(const ts_event_handler_instance_t *handler, +@@ -718,7 +764,7 @@ static bool handler_matches(const ts_event_handler_instance_t *handler, + } + + // 检查事件基础 +- if (handler->base != TS_EVENT_ANY_BASE && handler->base != NULL) { ++ if (handler->base != NULL && strcmp(handler->base, TS_EVENT_ANY_BASE) != 0) { + if (event->base == NULL || strcmp(handler->base, event->base) != 0) { + return false; + } +diff --git a/components/ts_net/include/ts_http_server.h b/components/ts_net/include/ts_http_server.h +index 9e18598..e79d91b 100644 +--- a/components/ts_net/include/ts_http_server.h ++++ b/components/ts_net/include/ts_http_server.h +@@ -123,6 +123,12 @@ esp_err_t ts_http_set_cors(ts_http_request_t *req, const char *origin); + */ + httpd_handle_t ts_http_server_get_handle(void); + ++/* Owner hooks: before_stop must drain users; failure preserves the live handle. */ ++void ts_http_server_set_stop_hooks(esp_err_t (*before)(httpd_handle_t), ++ void (*after)(httpd_handle_t)); ++ ++bool ts_http_server_is_stopping(void); ++ + #ifdef __cplusplus + } + #endif +diff --git a/components/ts_net/src/ts_http_server.c b/components/ts_net/src/ts_http_server.c +index a8f7726..edb8086 100644 +--- a/components/ts_net/src/ts_http_server.c ++++ b/components/ts_net/src/ts_http_server.c +@@ -12,12 +12,30 @@ + #include "esp_log.h" + #include "esp_heap_caps.h" + #include ++#include ++#include "freertos/task.h" + + #define TAG "ts_http" + #define MAX_ROUTES 64 + + static httpd_handle_t s_server = NULL; + static bool s_initialized = false; ++static _Atomic(TaskHandle_t) s_http_task; ++static atomic_flag s_stop_busy = ATOMIC_FLAG_INIT; ++static atomic_bool s_stopping; ++bool ts_http_server_is_stopping(void) { return s_stopping; } ++static esp_err_t session_open(httpd_handle_t server, int fd) ++{ ++ (void)server; (void)fd; ++ s_http_task = xTaskGetCurrentTaskHandle(); ++ return ESP_OK; ++} ++static esp_err_t (*s_before_stop)(httpd_handle_t); ++static void (*s_after_stop)(httpd_handle_t); ++void ts_http_server_set_stop_hooks(esp_err_t (*before)(httpd_handle_t), void (*after)(httpd_handle_t)) ++{ ++ s_before_stop = before; s_after_stop = after; ++} + + // 路由注册表(用于同步到 HTTPS) + typedef struct { +@@ -26,6 +44,7 @@ typedef struct { + ts_http_handler_t handler; + void *user_data; // 原始 user_data + bool requires_auth; // 认证要求 ++ ts_http_route_t *owned_copy; /* HTTPD borrows user_ctx; it does not free it. */ + } registered_route_t; + + static registered_route_t s_registered_routes[MAX_ROUTES]; +@@ -46,19 +65,22 @@ esp_err_t ts_http_server_init(void) + + esp_err_t ts_http_server_deinit(void) + { +- ts_http_server_stop(); ++ esp_err_t ret = ts_http_server_stop(); ++ if (ret != ESP_OK) return ret; + s_initialized = false; + return ESP_OK; + } + + esp_err_t ts_http_server_start(void) + { ++ if (s_stopping) return ESP_ERR_INVALID_STATE; + if (s_server) return ESP_OK; + + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + #ifdef CONFIG_TS_NET_HTTP_PORT + config.server_port = CONFIG_TS_NET_HTTP_PORT; + #endif ++ config.open_fn = session_open; + config.max_uri_handlers = MAX_ROUTES; + config.uri_match_fn = httpd_uri_match_wildcard; + config.global_user_ctx = NULL; +@@ -81,12 +103,27 @@ esp_err_t ts_http_server_start(void) + + esp_err_t ts_http_server_stop(void) + { +- if (!s_server) return ESP_OK; +- +- httpd_stop(s_server); ++ if (s_http_task && s_http_task == xTaskGetCurrentTaskHandle()) return ESP_ERR_INVALID_STATE; ++ if (atomic_flag_test_and_set(&s_stop_busy)) return ESP_ERR_INVALID_STATE; ++ esp_err_t ret = ESP_OK; ++ if (!s_server) goto done; ++ s_stopping = true; ++ ret = s_before_stop ? s_before_stop(s_server) : ESP_OK; ++ if (ret != ESP_OK) goto done; ++ httpd_handle_t stopped = s_server; ++ ret = httpd_stop(stopped); ++ if (ret != ESP_OK) goto done; ++ if (s_after_stop) s_after_stop(stopped); + s_server = NULL; ++ s_http_task = NULL; ++ s_stopping = false; ++ for (int i = 0; i < s_route_count; ++i) free(s_registered_routes[i].owned_copy); ++ memset(s_registered_routes, 0, sizeof(s_registered_routes)); ++ s_route_count = 0; + TS_LOGI(TAG, "HTTP server stopped"); +- return ESP_OK; ++done: ++ atomic_flag_clear(&s_stop_busy); ++ return ret; + } + + static esp_err_t http_handler_wrapper(httpd_req_t *req) +@@ -145,7 +182,8 @@ static esp_err_t http_handler_wrapper(httpd_req_t *req) + + esp_err_t ts_http_server_register_route(const ts_http_route_t *route) + { +- if (!s_server || !route) return ESP_ERR_INVALID_STATE; ++ if (!s_server || !route || s_stopping) return ESP_ERR_INVALID_STATE; ++ if (s_route_count >= MAX_ROUTES) return ESP_ERR_NO_MEM; + + // Allocate persistent copy of route (prefer PSRAM) + ts_http_route_t *route_copy = TS_MALLOC_PSRAM(sizeof(ts_http_route_t)); +@@ -173,6 +211,7 @@ esp_err_t ts_http_server_register_route(const ts_http_route_t *route) + s_registered_routes[s_route_count].method = route->method; + s_registered_routes[s_route_count].handler = route->handler; + s_registered_routes[s_route_count].user_data = route->user_data; // 保存 user_data ++ s_registered_routes[s_route_count].owned_copy = route_copy; + s_registered_routes[s_route_count].requires_auth = route->requires_auth; // 保存认证要求 + s_route_count++; + } +diff --git a/components/ts_webui/CMakeLists.txt b/components/ts_webui/CMakeLists.txt +index b9383bd..666c0de 100644 +--- a/components/ts_webui/CMakeLists.txt ++++ b/components/ts_webui/CMakeLists.txt +@@ -4,6 +4,7 @@ idf_component_register( + "src/ts_webui_api.c" + "src/ts_webui_ws.c" + "src/ts_ws_subscriptions.c" ++ "src/ts_ws_transport.c" + INCLUDE_DIRS + "include" + REQUIRES +diff --git a/components/ts_webui/include/ts_ws_subscriptions.h b/components/ts_webui/include/ts_ws_subscriptions.h +index 2248018..37bb0be 100644 +--- a/components/ts_webui/include/ts_ws_subscriptions.h ++++ b/components/ts_webui/include/ts_ws_subscriptions.h +@@ -9,6 +9,7 @@ + #pragma once + + #include "esp_err.h" ++#include "ts_ws_transport.h" + #include "ts_event.h" + #include "cJSON.h" + #include +@@ -27,33 +28,33 @@ esp_err_t ts_ws_subscriptions_init(void); + /** + * @brief 反初始化订阅管理器 + */ +-void ts_ws_subscriptions_deinit(void); ++esp_err_t ts_ws_subscriptions_deinit(void); + + /** + * @brief 处理订阅请求 + * +- * @param fd 客户端文件描述符 ++ * @param peer 已登记的 HTTPD 会话身份(不能只传 fd) + * @param topic 订阅主题 (e.g., "device.status", "ota.progress") + * @param params JSON 参数对象 (可选) + * @return ESP_OK on success + */ +-esp_err_t ts_ws_subscribe(int fd, const char *topic, cJSON *params); ++esp_err_t ts_ws_subscribe(ts_ws_peer_t peer, const char *topic, cJSON *params); + + /** + * @brief 处理取消订阅请求 + * +- * @param fd 客户端文件描述符 ++ * @param peer 已登记的 HTTPD 会话身份(不能只传 fd) + * @param topic 订阅主题 + * @return ESP_OK on success + */ +-esp_err_t ts_ws_unsubscribe(int fd, const char *topic); ++esp_err_t ts_ws_unsubscribe(ts_ws_peer_t peer, const char *topic); + + /** + * @brief 客户端断开连接时清理订阅 + * +- * @param fd 客户端文件描述符 ++ * @param peer 已登记的 HTTPD 会话身份(不能只传 fd) + */ +-void ts_ws_client_disconnected(int fd); ++void ts_ws_client_disconnected(ts_ws_peer_t peer); + + /** + * @brief 广播数据到订阅了特定 topic 的客户端 +diff --git a/components/ts_webui/src/ts_webui.c b/components/ts_webui/src/ts_webui.c +index 3184c7b..80abb4a 100644 +--- a/components/ts_webui/src/ts_webui.c ++++ b/components/ts_webui/src/ts_webui.c +@@ -87,8 +87,10 @@ esp_err_t ts_webui_deinit(void) + { + if (!s_initialized) return ESP_OK; + +- ts_webui_stop(); +- ts_http_server_deinit(); ++ esp_err_t ret = ts_webui_stop(); ++ if (ret != ESP_OK) return ret; ++ ret = ts_http_server_deinit(); ++ if (ret != ESP_OK) return ret; + + s_initialized = false; + return ESP_OK; +@@ -96,7 +98,7 @@ esp_err_t ts_webui_deinit(void) + + esp_err_t ts_webui_start(void) + { +- if (s_running) return ESP_OK; ++ if (s_running && ts_http_server_get_handle() && !ts_http_server_is_stopping()) return ESP_OK; + if (!s_initialized) { + esp_err_t ret = ts_webui_init(); + if (ret != ESP_OK) return ret; +@@ -120,6 +122,8 @@ esp_err_t ts_webui_start(void) + ret = ts_webui_ws_init(); + if (ret != ESP_OK) { + TS_LOGW(TAG, "WebSocket init failed"); ++ esp_err_t stop_ret = ts_http_server_stop(); ++ return stop_ret != ESP_OK ? stop_ret : ret; + } + #endif + +@@ -140,9 +144,9 @@ esp_err_t ts_webui_start(void) + + esp_err_t ts_webui_stop(void) + { +- if (!s_running) return ESP_OK; + +- ts_http_server_stop(); ++ esp_err_t ret = ts_http_server_stop(); ++ if (ret != ESP_OK) return ret; + s_running = false; + + TS_LOGI(TAG, "WebUI stopped"); +@@ -151,5 +155,5 @@ esp_err_t ts_webui_stop(void) + + bool ts_webui_is_running(void) + { +- return s_running; ++ return s_running && ts_http_server_get_handle() && !ts_http_server_is_stopping(); + } +diff --git a/components/ts_webui/src/ts_webui_ws.c b/components/ts_webui/src/ts_webui_ws.c +index 96a44dc..c853e39 100644 +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -13,6 +13,9 @@ + #include "ts_ssh_shell.h" + #include "ts_keystore.h" + #include "ts_ws_subscriptions.h" ++#include "ts_ws_transport.h" ++#include ++#include "esp_timer.h" + // ts_var.h 已废弃,统一使用 ts_variable.h(ts_automation 变量系统) + #include "ts_variable.h" + #include "esp_http_server.h" +@@ -52,15 +55,17 @@ typedef enum { + } ws_client_type_t; + + typedef struct { +- bool active; +- int fd; +- httpd_handle_t hd; +- ws_client_type_t type; +- ts_log_level_t log_min_level; // 日志客户端的最小级别过滤 ++ atomic_bool active; ++ atomic_int fd; ++ _Atomic(httpd_handle_t) hd; ++ _Atomic(ws_client_type_t) type; ++ _Atomic(ts_log_level_t) log_min_level; // 日志客户端的最小级别过滤 + } ws_client_t; + + static ws_client_t s_clients[MAX_WS_CLIENTS]; +-static httpd_handle_t s_server = NULL; ++static _Atomic(httpd_handle_t) s_server = NULL; ++static ts_ws_peer_t s_ssh_peer; ++static atomic_bool s_ws_stopping; + static SemaphoreHandle_t s_terminal_mutex = NULL; + static int s_terminal_client_fd = -1; // 当前终端会话的 fd + +@@ -72,14 +77,15 @@ static SemaphoreHandle_t s_output_mutex = NULL; + /* SSH Shell 会话状态 */ + static ts_ssh_session_t s_ssh_session = NULL; + static ts_ssh_shell_t s_ssh_shell = NULL; +-static int s_ssh_client_fd = -1; +-static TaskHandle_t s_ssh_poll_task = NULL; +-static volatile bool s_ssh_running = false; ++static atomic_int s_ssh_client_fd = -1; ++static atomic_bool s_ssh_running = false; ++static atomic_bool s_ssh_poll_alive; + + /* SSH Exec 流式执行状态 */ + static ts_ssh_session_t s_exec_session = NULL; + static TaskHandle_t s_exec_task = NULL; +-static volatile bool s_exec_running = false; ++static atomic_bool s_exec_running = false; ++static atomic_uint s_exec_creators; + static volatile bool s_exec_cancel_requested = false; /* 实时匹配触发的取消请求 */ + static volatile uint32_t s_exec_session_id = 0; + static TimerHandle_t s_exec_timeout_timer = NULL; /* 超时定时器 */ +@@ -96,6 +102,8 @@ static const char *s_level_names[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", + + /* 前向声明 */ + static void update_log_stream_state(void); ++esp_err_t ts_webui_ws_stop(httpd_handle_t server); ++void ts_webui_ws_stopped(httpd_handle_t server); + static bool has_log_clients(void); + + /* 电压保护状态字符串 */ +@@ -159,16 +167,6 @@ static void ssh_send_output(const char *data, size_t len) + { + if (s_ssh_client_fd < 0 || !s_server || !data || len == 0) return; + +- // 查找客户端 +- httpd_handle_t hd = NULL; +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { +- hd = s_clients[i].hd; +- break; +- } +- } +- if (!hd) return; +- + // 构造消息(base64 可以处理二进制,但这里假设是文本) + cJSON *msg = cJSON_CreateObject(); + cJSON_AddStringToObject(msg, "type", "ssh_output"); +@@ -192,7 +190,11 @@ static void ssh_send_output(const char *data, size_t len) + .payload = (uint8_t *)json, + .len = strlen(json) + }; +- httpd_ws_send_frame_async(hd, s_ssh_client_fd, &ws_pkt); ++ ts_ws_message_t *owned = ts_ws_message_text((const char *)ws_pkt.payload, ws_pkt.len); ++ if (owned) { ++ ts_ws_transport_submit(s_ssh_peer, owned, 0, 0, NULL, NULL); ++ ts_ws_message_release(owned); ++ } + free(json); + } + } +@@ -201,16 +203,7 @@ static void ssh_send_output(const char *data, size_t len) + static void ssh_send_status(const char *status, const char *message) + { + if (s_ssh_client_fd < 0 || !s_server) return; +- +- httpd_handle_t hd = NULL; +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { +- hd = s_clients[i].hd; +- break; +- } +- } +- if (!hd) return; +- ++ + cJSON *msg = cJSON_CreateObject(); + cJSON_AddStringToObject(msg, "type", "ssh_status"); + cJSON_AddStringToObject(msg, "status", status); +@@ -227,7 +220,11 @@ static void ssh_send_status(const char *status, const char *message) + .payload = (uint8_t *)json, + .len = strlen(json) + }; +- httpd_ws_send_frame_async(hd, s_ssh_client_fd, &ws_pkt); ++ ts_ws_message_t *owned = ts_ws_message_text((const char *)ws_pkt.payload, ws_pkt.len); ++ if (owned) { ++ ts_ws_transport_submit(s_ssh_peer, owned, 0, 0, NULL, NULL); ++ ts_ws_message_release(owned); ++ } + free(json); + } + } +@@ -264,7 +261,6 @@ static void ssh_poll_task(void *arg) + } + + TS_LOGD(TAG, "SSH poll task ended"); +- s_ssh_poll_task = NULL; + + // 如果是因为远程关闭而退出,需要清理 SSH 会话 + if (need_cleanup && s_ssh_session) { +@@ -279,19 +275,13 @@ static void ssh_poll_task(void *arg) + ts_ssh_session_destroy(s_ssh_session); + s_ssh_session = NULL; + } +- // 更新客户端类型 +- if (s_ssh_client_fd >= 0) { +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { +- s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; +- break; +- } +- } +- s_ssh_client_fd = -1; +- } ++ /* Legacy UI type is changed only by the HTTPD owner. A retired SSH ++ * worker must not change a replacement connection that reuses its fd. */ ++ s_ssh_client_fd = -1; + TS_LOGD(TAG, "SSH session cleaned up after remote close"); + } + ++ s_ssh_poll_alive = false; + vTaskDelete(NULL); + } + +@@ -300,9 +290,10 @@ static void ssh_cleanup(void) + { + s_ssh_running = false; + +- if (s_ssh_poll_task) { +- // 等待任务结束 +- vTaskDelay(pdMS_TO_TICKS(100)); ++ int64_t deadline = esp_timer_get_time() + 2000000; ++ while (s_ssh_poll_alive) { ++ if (esp_timer_get_time() >= deadline) return; /* retain resources for retry */ ++ vTaskDelay(1); + } + + if (s_ssh_shell) { +@@ -333,6 +324,11 @@ static void ssh_cleanup(void) + /* 处理 SSH Shell 连接请求 */ + static void handle_ssh_connect(httpd_req_t *req, cJSON *params) + { ++ if (s_ssh_poll_alive) { ++ ssh_send_status("error", "Another SSH session is active"); ++ return; ++ } ++ + int fd = httpd_req_to_sockfd(req); + + // 检查是否已有 SSH 会话 +@@ -358,6 +354,7 @@ static void handle_ssh_connect(httpd_req_t *req, cJSON *params) + TS_LOGD(TAG, "SSH connect: %s@%s:%d", user->valuestring, host->valuestring, ssh_port); + + // 设置 SSH 客户端 fd ++ s_ssh_peer = *(ts_ws_peer_t *)req->sess_ctx; + s_ssh_client_fd = fd; + + // 更新客户端类型 +@@ -416,7 +413,12 @@ static void handle_ssh_connect(httpd_req_t *req, cJSON *params) + + // 启动轮询任务(栈需要足够大以容纳 libssh2 缓冲区,使用 PSRAM) + s_ssh_running = true; +- xTaskCreateWithCaps(ssh_poll_task, "ssh_poll", 4096, NULL, 5, &s_ssh_poll_task, MALLOC_CAP_SPIRAM); ++ s_ssh_poll_alive = true; ++ if (xTaskCreateWithCaps(ssh_poll_task, "ssh_poll", 4096, NULL, 5, NULL, MALLOC_CAP_SPIRAM) != pdPASS) { ++ s_ssh_poll_alive = false; ++ ssh_send_status("error", "Failed to create SSH session"); ++ ssh_cleanup(); ++ } + } + + /* 处理 SSH Shell 输入 */ +@@ -484,76 +486,21 @@ static void terminal_output_cb(const char *data, size_t len, void *user_data) + /* 前向声明 */ + static void cleanup_disconnected_client(int fd); + +-static void add_client(httpd_handle_t hd, int fd, ws_client_type_t type) ++static esp_err_t add_client(httpd_req_t *req, ws_client_type_t type) + { +- // 首先检查是否已存在相同 fd 的客户端(重连情况) +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].fd == fd) { +- // 已存在,更新类型 +- s_clients[i].type = type; +- s_clients[i].hd = hd; +- TS_LOGD(TAG, "WebSocket client reconnected (fd=%d, type=%s)", +- fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "event"); +- return; +- } +- } +- +- // 查找空槽位 +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (!s_clients[i].active) { +- s_clients[i].active = true; +- s_clients[i].fd = fd; +- s_clients[i].hd = hd; +- s_clients[i].type = type; +- TS_LOGD(TAG, "WebSocket client connected (fd=%d, type=%s)", +- fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "event"); +- return; +- } +- } +- +- // 没有空槽位,尝试清理可能已断开但未标记的连接 +- TS_LOGW(TAG, "No free WebSocket slots, attempting to clean up stale connections..."); +- int oldest_event_slot = -1; +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active) { +- // 检查 socket 状态(使用 recv 探测,MSG_PEEK | MSG_DONTWAIT) +- char probe; +- int result = recv(s_clients[i].fd, &probe, 1, MSG_PEEK | MSG_DONTWAIT); +- if (result == 0 || (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK)) { +- // Socket 已关闭或错误 +- int old_fd = s_clients[i].fd; +- TS_LOGI(TAG, "Cleaned up stale connection (fd=%d, recv=%d, errno=%d)", old_fd, result, errno); +- cleanup_disconnected_client(old_fd); +- // cleanup_disconnected_client 已经设置 active=false,现在可以使用这个槽位 +- s_clients[i].active = true; +- s_clients[i].fd = fd; +- s_clients[i].hd = hd; +- s_clients[i].type = type; +- TS_LOGD(TAG, "WebSocket client connected after cleanup (fd=%d, type=%s)", +- fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "event"); +- return; +- } +- // 记录最旧的普通事件客户端槽位(非终端/SSH) +- if (s_clients[i].type == WS_CLIENT_TYPE_EVENT && oldest_event_slot < 0) { +- oldest_event_slot = i; +- } +- } +- } +- +- // 如果所有连接都活跃,且新连接是终端/SSH,抢占最旧的事件客户端 +- if ((type == WS_CLIENT_TYPE_TERMINAL || type == WS_CLIENT_TYPE_SSH_SHELL) && oldest_event_slot >= 0) { +- int evicted_fd = s_clients[oldest_event_slot].fd; +- TS_LOGW(TAG, "All slots full, evicting oldest event client (fd=%d) for %s", +- evicted_fd, type == WS_CLIENT_TYPE_TERMINAL ? "terminal" : "ssh"); +- cleanup_disconnected_client(evicted_fd); +- s_clients[oldest_event_slot].active = true; +- s_clients[oldest_event_slot].fd = fd; +- s_clients[oldest_event_slot].hd = hd; +- s_clients[oldest_event_slot].type = type; +- return; ++ ts_ws_peer_t peer; ++ esp_err_t ret = ts_ws_peer_open(req, &peer); ++ if (ret != ESP_OK) return ret; ++ for (int i = 0; i < MAX_WS_CLIENTS; ++i) if (!s_clients[i].active) { ++ s_clients[i].fd = peer.fd; ++ s_clients[i].hd = peer.server; ++ s_clients[i].type = type; ++ s_clients[i].log_min_level = TS_LOG_NONE; ++ s_clients[i].active = true; ++ return ESP_OK; + } +- +- TS_LOGE(TAG, "All WebSocket slots are occupied by active connections"); ++ ts_ws_peer_close(peer); ++ return ESP_ERR_NO_MEM; + } + + /* 处理终端命令执行 */ +@@ -682,7 +629,7 @@ static void start_terminal_session(httpd_req_t *req) + .payload = (uint8_t *)close_json, + .len = strlen(close_json) + }; +- httpd_ws_send_frame_async(old_hd, s_terminal_client_fd, &ws_pkt); ++ ts_ws_transport_send(old_hd, s_terminal_client_fd, &ws_pkt); + free(close_json); + } + +@@ -734,7 +681,11 @@ static void cleanup_disconnected_client(int fd) + bool was_log_client = false; + + // 清理订阅(新增) +- ts_ws_client_disconnected(fd); ++ ts_ws_peer_t peer; ++ if (ts_ws_peer_get(s_server, fd, &peer)) { ++ ts_ws_peer_close(peer); ++ return; ++ } + + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { +@@ -766,15 +717,26 @@ static void cleanup_disconnected_client(int fd) + } + } + ++static void peer_closed(ts_ws_peer_t peer) ++{ ++ ts_ws_client_disconnected(peer); ++ cleanup_disconnected_client(peer.fd); ++} ++ + static esp_err_t ws_handler(httpd_req_t *req) + { ++ if (s_ws_stopping) return ESP_ERR_INVALID_STATE; + if (req->method == HTTP_GET) { + TS_LOGD(TAG, "WebSocket handshake"); + // 初次连接时添加为事件客户端 +- add_client(req->handle, httpd_req_to_sockfd(req), WS_CLIENT_TYPE_EVENT); +- return ESP_OK; ++ if (s_ws_stopping) return ESP_ERR_INVALID_STATE; ++ return add_client(req, WS_CLIENT_TYPE_EVENT); + } + ++ ts_ws_peer_t peer; ++ if (!req->sess_ctx || !ts_ws_peer_get(req->handle, httpd_req_to_sockfd(req), &peer) || ++ !ts_ws_peer_equal(peer, *(ts_ws_peer_t *)req->sess_ctx)) return ESP_ERR_INVALID_STATE; ++ + httpd_ws_frame_t ws_pkt; + memset(&ws_pkt, 0, sizeof(ws_pkt)); + ws_pkt.type = HTTPD_WS_TYPE_TEXT; +@@ -810,6 +772,7 @@ static esp_err_t ws_handler(httpd_req_t *req) + + ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len); + if (ret != ESP_OK) { ++ cleanup_disconnected_client(httpd_req_to_sockfd(req)); + free(buf); + return ret; + } +@@ -840,12 +803,11 @@ static esp_err_t ws_handler(httpd_req_t *req) + } + else if (strcmp(type->valuestring, "subscribe") == 0) { + // 处理订阅请求(新增:topic 订阅) +- int fd = httpd_req_to_sockfd(req); + cJSON *topic = cJSON_GetObjectItem(msg, "topic"); + cJSON *params = cJSON_GetObjectItem(msg, "params"); + + if (topic && cJSON_IsString(topic)) { +- esp_err_t ret = ts_ws_subscribe(fd, topic->valuestring, params); ++ esp_err_t ret = ts_ws_subscribe(*(ts_ws_peer_t *)req->sess_ctx, topic->valuestring, params); + + // 发送确认消息 + cJSON *ack = cJSON_CreateObject(); +@@ -871,11 +833,10 @@ static esp_err_t ws_handler(httpd_req_t *req) + } + else if (strcmp(type->valuestring, "unsubscribe") == 0) { + // 处理取消订阅请求(新增) +- int fd = httpd_req_to_sockfd(req); + cJSON *topic = cJSON_GetObjectItem(msg, "topic"); + + if (topic && cJSON_IsString(topic)) { +- esp_err_t ret = ts_ws_unsubscribe(fd, topic->valuestring); ++ esp_err_t ret = ts_ws_unsubscribe(*(ts_ws_peer_t *)req->sess_ctx, topic->valuestring); + + // 发送确认消息 + cJSON *ack = cJSON_CreateObject(); +@@ -919,6 +880,7 @@ static esp_err_t ws_handler(httpd_req_t *req) + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { + s_clients[i].type = WS_CLIENT_TYPE_EVENT; ++ ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, -1); + break; + } + } +@@ -971,6 +933,7 @@ static esp_err_t ws_handler(httpd_req_t *req) + if (s_clients[i].active && s_clients[i].fd == fd) { + s_clients[i].type = WS_CLIENT_TYPE_LOG; + s_clients[i].log_min_level = min_level; ++ ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, min_level); + client_found = true; + TS_LOGI(TAG, "Client %d subscribed to logs (minLevel=%d)", i, min_level); + break; +@@ -1003,6 +966,7 @@ static esp_err_t ws_handler(httpd_req_t *req) + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { + s_clients[i].type = WS_CLIENT_TYPE_EVENT; ++ ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, -1); + break; + } + } +@@ -1018,6 +982,7 @@ static esp_err_t ws_handler(httpd_req_t *req) + if (s_clients[i].active && s_clients[i].fd == fd && + s_clients[i].type == WS_CLIENT_TYPE_LOG) { + s_clients[i].log_min_level = (ts_log_level_t)level->valueint; ++ ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, level->valueint); + break; + } + } +@@ -1089,6 +1054,14 @@ esp_err_t ts_webui_ws_init(void) + { + TS_LOGI(TAG, "Initializing WebSocket with Terminal support"); + ++ httpd_handle_t server = ts_http_server_get_handle(); ++ if (!server) return ESP_ERR_INVALID_STATE; ++ if (s_server) return s_ws_stopping ? ESP_ERR_INVALID_STATE : ESP_OK; ++ esp_err_t transport_ret = ts_ws_transport_start(server, peer_closed); ++ if (transport_ret != ESP_OK) return transport_ret; ++ s_server = server; ++ s_ws_stopping = false; ++ ts_http_server_set_stop_hooks(ts_webui_ws_stop, ts_webui_ws_stopped); + memset(s_clients, 0, sizeof(s_clients)); + s_terminal_client_fd = -1; + +@@ -1109,6 +1082,8 @@ esp_err_t ts_webui_ws_init(void) + s_output_mutex = xSemaphoreCreateMutex(); + } + ++ if (!s_terminal_mutex || !s_output_mutex) return ESP_ERR_NO_MEM; ++ + // 分配终端输出缓冲区(优先使用 PSRAM) + if (!s_terminal_output_buf) { + s_terminal_output_buf = heap_caps_malloc(TERMINAL_OUTPUT_BUF_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +@@ -1128,7 +1103,6 @@ esp_err_t ts_webui_ws_init(void) + } + + // Get HTTP server handle +- httpd_handle_t server = ts_http_server_get_handle(); + if (!server) { + TS_LOGE(TAG, "HTTP server not started"); + return ESP_ERR_INVALID_STATE; +@@ -1160,6 +1134,7 @@ esp_err_t ts_webui_ws_init(void) + TS_LOGI(TAG, "Power policy event handler registered"); + } else { + TS_LOGW(TAG, "Failed to register power event handler: %s", esp_err_to_name(ret)); ++ return ret; + } + } + +@@ -1167,6 +1142,34 @@ esp_err_t ts_webui_ws_init(void) + return ESP_OK; + } + ++esp_err_t ts_webui_ws_stop(httpd_handle_t server) ++{ ++ if (ts_ws_transport_in_context() || ts_event_in_callback()) return ESP_ERR_INVALID_STATE; ++ s_ws_stopping = true; ++ esp_err_t ret = ts_ws_subscriptions_deinit(); ++ if (ret != ESP_OK) return ret; ++ ret = ts_ws_transport_quiesce(server, 6000); ++ if (ret != ESP_OK) return ret; ++ if (s_power_event_handle) { ++ ret = ts_event_unregister_sync(s_power_event_handle, 6000); ++ if (ret != ESP_OK && ret != ESP_ERR_NOT_FOUND) return ret; ++ s_power_event_handle = NULL; ++ } ++ /* Do not destroy a running remote operation or replay it. Keep HTTPD alive ++ * and return busy; the control caller can retry after its normal completion. */ ++ if (s_exec_creators || s_exec_running) return ESP_ERR_INVALID_STATE; ++ ssh_cleanup(); ++ if (s_ssh_poll_alive) return ESP_ERR_TIMEOUT; ++ return ts_ws_transport_stop(server, 6000); ++} ++ ++void ts_webui_ws_stopped(httpd_handle_t server) ++{ ++ ts_ws_transport_stopped(server); ++ if (s_server == server) s_server = NULL; ++ /* Existing terminal buffer/mutex are stable reusable singleton resources. */ ++} ++ + esp_err_t ts_webui_broadcast(const char *message) + { + if (!message) return ESP_ERR_INVALID_ARG; +@@ -1177,23 +1180,7 @@ esp_err_t ts_webui_broadcast(const char *message) + .len = strlen(message) + }; + +- int sent = 0; +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active) { +- esp_err_t ret = httpd_ws_send_frame_async(s_clients[i].hd, s_clients[i].fd, &ws_pkt); +- if (ret == ESP_OK) { +- sent++; +- } else { +- // Client probably disconnected - cleanup resources +- int fd = s_clients[i].fd; +- TS_LOGW(TAG, "Client fd=%d send failed, cleaning up", fd); +- cleanup_disconnected_client(fd); +- } +- } +- } +- +- TS_LOGD(TAG, "Broadcast to %d clients", sent); +- return ESP_OK; ++ return ts_ws_transport_broadcast(&ws_pkt); + } + + esp_err_t ts_webui_broadcast_event(const char *event_type, const char *data) +@@ -1265,23 +1252,8 @@ static void log_ws_callback(const ts_log_entry_t *entry, void *user_data) + .len = strlen(json) + }; + +- // 发送给所有日志订阅客户端(根据级别过滤) +- int sent_count = 0; +- for (int i = 0; i < MAX_WS_CLIENTS; i++) { +- if (s_clients[i].active && s_clients[i].type == WS_CLIENT_TYPE_LOG) { +- // 检查级别过滤 +- if (entry->level <= s_clients[i].log_min_level) { +- httpd_ws_send_frame_async(s_clients[i].hd, s_clients[i].fd, &ws_pkt); +- sent_count++; +- } +- } +- } +- +- // Debug: Log if no clients received the message +- if (sent_count == 0) { +- TS_LOGD(TAG, "log_ws_callback: No clients received log (level=%d)", entry->level); +- } +- ++ ts_ws_transport_log(&ws_pkt, entry->level); ++ + free(json); + } + +@@ -2034,7 +2006,7 @@ cleanup: + vTaskDelete(NULL); + } + +-esp_err_t ts_webui_ssh_exec_start(const char *host, uint16_t port, ++static esp_err_t ts_webui_ssh_exec_start_impl(const char *host, uint16_t port, + const char *user, const char *keyid, + const char *password, const char *command, + uint32_t *session_id) +@@ -2131,8 +2103,19 @@ esp_err_t ts_webui_ssh_exec_start(const char *host, uint16_t port, + return ESP_OK; + } + ++esp_err_t ts_webui_ssh_exec_start(const char *host, uint16_t port, ++ const char *user, const char *keyid, ++ const char *password, const char *command, ++ uint32_t *session_id) ++{ ++ unsigned creators = atomic_fetch_add(&s_exec_creators, 1); ++ esp_err_t ret = (creators || s_ws_stopping) ? ESP_ERR_INVALID_STATE : ts_webui_ssh_exec_start_impl(host, port, user, keyid, password, command, session_id); ++ atomic_fetch_sub(&s_exec_creators, 1); ++ return ret; ++} ++ + /* 带选项的扩展版本 */ +-esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, ++static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char *host, uint16_t port, + const char *user, const char *keyid, + const char *password, const char *command, + const ts_webui_ssh_options_t *options, +@@ -2335,6 +2318,18 @@ esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, + return ESP_OK; + } + ++esp_err_t ts_webui_ssh_exec_start_ex(const char *host, uint16_t port, ++ const char *user, const char *keyid, ++ const char *password, const char *command, ++ const ts_webui_ssh_options_t *options, ++ uint32_t *session_id) ++{ ++ unsigned creators = atomic_fetch_add(&s_exec_creators, 1); ++ esp_err_t ret = (creators || s_ws_stopping) ? ESP_ERR_INVALID_STATE : ts_webui_ssh_exec_start_ex_impl(host, port, user, keyid, password, command, options, session_id); ++ atomic_fetch_sub(&s_exec_creators, 1); ++ return ret; ++} ++ + /* 释放结果结构 */ + void ts_webui_ssh_result_free(ts_webui_ssh_result_t *result) + { +diff --git a/components/ts_webui/src/ts_ws_subscriptions.c b/components/ts_webui/src/ts_ws_subscriptions.c +index 8ad8f51..b492ef2 100644 +--- a/components/ts_webui/src/ts_ws_subscriptions.c ++++ b/components/ts_webui/src/ts_ws_subscriptions.c +@@ -1,654 +1,414 @@ +-/** +- * @file ts_ws_subscriptions.c +- * @brief WebSocket Subscription Manager Implementation +- */ +- ++/** Demand-driven display telemetry. Hardware sampling/control is not scheduled here. */ + #include "ts_ws_subscriptions.h" +-#include "ts_webui.h" +-#include "ts_log.h" +-#include "ts_event.h" ++#include "ts_ws_transport.h" + #include "ts_api.h" ++#include "ts_log.h" + #include "esp_timer.h" + #include "freertos/FreeRTOS.h" +-#include "freertos/semphr.h" ++#include "freertos/task.h" ++#include + #include +- +-#define TAG "ws_subs" ++#include + + #define MAX_SUBSCRIPTIONS 32 +-#define MAX_TOPIC_LEN 32 +- ++#define EVENT_SLOTS 4 ++#define WORKER_STACK 8192 ++#define STOP_TIMEOUT_MS 6000 ++#define TAG "ws_subs" ++static const struct { const char *name; uint32_t interval; int metric; } topics[] = { ++ {"system.dashboard",1000,-1}, {"system.info",5000,2}, ++ {"system.memory",5000,1}, {"system.cpu",1000,0}, ++ {"network.status",5000,3}, {"power.status",5000,4}, ++ {"fan.status",5000,5}, {"service.list",5000,6}, ++ {"device.status",2000,-2}, {"ota.progress",1000,-2}, ++ {"config.pack.validated",0,-2} ++}; ++#define TOPIC_COUNT (sizeof(topics)/sizeof(topics[0])) ++static const char *metrics[] = {"system.cpu","system.memory","system.info", ++ "network.status","power.status","fan.status","service.list"}; ++static const char *fields[] = {"cpu","memory","info","network","power","fan","services"}; ++typedef enum { OFF, STARTING, RUNNING, STOPPING } lifecycle_t; + typedef struct { +- int fd; // 客户端文件描述符 +- char topic[MAX_TOPIC_LEN]; // 订阅的主题 +- uint32_t min_interval_ms; // 最小推送间隔(去抖动) +- int64_t last_broadcast_time; // 上次广播时间戳(微秒) +- bool active; // 订阅是否激活 ++ ts_ws_peer_t peer; ++ uint64_t revision, pending; ++ int64_t last_success, next_attempt; ++ uint32_t interval; ++ unsigned topic; ++ bool active; + } subscription_t; +- + typedef struct { +- const char *topic; // 主题名称 +- ts_event_base_t event_base; // 事件基础 +- int32_t event_id; // 事件 ID +- uint32_t default_min_interval_ms; // 默认最小间隔 +-} topic_mapping_t; +- +-/* 订阅数组 */ +-static subscription_t s_subscriptions[MAX_SUBSCRIPTIONS]; +-static SemaphoreHandle_t s_subs_mutex = NULL; +- +-/* 事件处理器句柄 */ +-static ts_event_handler_handle_t s_system_event_handle = NULL; +-static ts_event_handler_handle_t s_device_event_handle = NULL; +-static ts_event_handler_handle_t s_ota_event_handle = NULL; +- +-/* 定时器句柄 */ +-static esp_timer_handle_t s_system_info_timer = NULL; /* 5s 间隔 */ +-static esp_timer_handle_t s_cpu_stats_timer = NULL; /* 1s 间隔 */ +-static esp_timer_handle_t s_dashboard_timer = NULL; /* 1s 间隔 - 聚合订阅 */ +- +-/* 主题映射表 */ +-static const topic_mapping_t s_topic_map[] = { +- {"system.dashboard", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 1000}, /* 聚合主题 */ +- {"system.info", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, +- {"system.memory", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, +- {"system.cpu", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 1000}, +- {"network.status", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, +- {"power.status", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, +- {"fan.status", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, +- {"service.list", TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, 5000}, +- {"device.status", TS_EVENT_BASE_DEVICE_MON, TS_EVENT_DEVICE_STATUS_CHANGED, 2000}, +- {"ota.progress", TS_EVENT_BASE_OTA, TS_EVENT_OTA_PROGRESS_UPDATE, 1000}, +- {"config.pack.validated", NULL, 0, 0}, /* 推送驱动主题 */ +-}; +-#define TOPIC_MAP_SIZE (sizeof(s_topic_map) / sizeof(s_topic_map[0])) +- +-/* 前向声明 */ +-static void system_event_handler(const ts_event_t *event, void *user_data); +-static void device_event_handler(const ts_event_t *event, void *user_data); +-static void ota_event_handler(const ts_event_t *event, void *user_data); +- +-/*===========================================================================*/ +-/* 辅助函数 */ +-/*===========================================================================*/ ++ ts_ws_peer_t peer; ++ uint64_t revision, delivery; ++ unsigned topic; ++} target_t; ++typedef struct { ++ bool used, ready; ++ uint64_t order; ++ ts_ws_message_t *message; ++ uint64_t targets[MAX_SUBSCRIPTIONS]; ++} event_item_t; ++/* Stable storage / spinlock survive init/deinit. Only short value mutations ++ * and task notifications under lock, never heap, API, JSON, queue or network. */ ++static portMUX_TYPE s_lock = portMUX_INITIALIZER_UNLOCKED; ++static lifecycle_t s_state; ++static bool s_stop_owner; ++static TaskHandle_t s_worker; ++static unsigned s_entries, s_outstanding; ++static uint64_t s_sequence; ++static subscription_t s_subs[MAX_SUBSCRIPTIONS]; ++static event_item_t s_events[EVENT_SLOTS]; ++static ts_event_handler_handle_t s_handlers[3]; ++static struct { ++ uint64_t api[7], batches[TOPIC_COUNT], serialized[TOPIC_COUNT]; ++ uint64_t queued, success, failure, stale, event_dropped, idle_wait, capacity_wait; ++ uint32_t stack_low_water; ++} s_stats; + +-/* 查找主题映射 */ +-static const topic_mapping_t *find_topic_mapping(const char *topic) ++static int64_t after_ms(int64_t now, uint32_t ms) + { +- for (int i = 0; i < TOPIC_MAP_SIZE; i++) { +- if (strcmp(s_topic_map[i].topic, topic) == 0) { +- return &s_topic_map[i]; +- } +- } +- return NULL; ++ int64_t delta = (int64_t)ms * 1000; ++ return now > INT64_MAX - delta ? INT64_MAX : now + delta; + } +- +-/* 检查是否需要广播(去抖动) */ +-static bool should_broadcast(subscription_t *sub) ++static void wake_locked(void) { if (s_worker) xTaskNotifyGive(s_worker); } ++void ts_ws_subscriptions_wake(void) + { +- int64_t now = esp_timer_get_time(); +- int64_t elapsed_ms = (now - sub->last_broadcast_time) / 1000; +- return (elapsed_ms >= sub->min_interval_ms); ++ portENTER_CRITICAL(&s_lock);wake_locked();portEXIT_CRITICAL(&s_lock); + } +- +-/* 查找或分配订阅槽位 */ +-static subscription_t *find_or_alloc_subscription(int fd, const char *topic) ++static int topic_id(const char *name) + { +- subscription_t *free_slot = NULL; +- +- // 查找已存在的订阅 +- for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { +- if (s_subscriptions[i].active && +- s_subscriptions[i].fd == fd && +- strcmp(s_subscriptions[i].topic, topic) == 0) { +- return &s_subscriptions[i]; +- } +- if (!s_subscriptions[i].active && !free_slot) { +- free_slot = &s_subscriptions[i]; +- } +- } +- +- return free_slot; ++ if (name) for (unsigned i=0;idata || event->data_size == 0) { +- return; +- } +- +- // 解析 JSON 字符串 +- cJSON *data = cJSON_Parse((const char *)event->data); +- if (data) { +- ts_ws_broadcast_to_topic("device.status", data); +- cJSON_Delete(data); +- } ++ for (unsigned i=0;idata || event->data_size == 0) { +- return; +- } +- +- // 解析 JSON 字符串 +- cJSON *data = cJSON_Parse((const char *)event->data); +- if (data) { +- ts_ws_broadcast_to_topic("ota.progress", data); +- cJSON_Delete(data); +- } ++ portENTER_CRITICAL(&s_lock); ++ subscription_t *s = find_revision(revision); ++ bool ok = s_state == RUNNING && s && s->pending == delivery; ++ portEXIT_CRITICAL(&s_lock); ++ return ok; + } +- +-/* 定时器回调:定期发送系统信息 */ +-static void system_info_timer_callback(void *arg) ++static void delivery_done(uint64_t revision, uint64_t delivery, esp_err_t result) + { +- // 发送系统信息事件 +- ts_event_post(TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_INFO_CHANGED, NULL, 0, 0); ++ int64_t now = esp_timer_get_time(); ++ portENTER_CRITICAL(&s_lock); ++ subscription_t *s = find_revision(revision); ++ if (s && s->pending == delivery) { ++ s->pending = 0; ++ if (result == ESP_OK) s->last_success = now; ++ /* Failure is not success. No catch-up burst and no retry of an old frame. */ ++ uint32_t delay = s->interval ? s->interval : (result == ESP_OK ? 0 : 1000); ++ s->next_attempt = after_ms(now, delay); ++ } else s_stats.stale++; ++ if (result == ESP_OK) s_stats.success++; else s_stats.failure++; ++ s_outstanding--; ++ wake_locked(); ++ portEXIT_CRITICAL(&s_lock); + } +- +-/* 定时器回调:CPU 统计 */ +-static void cpu_stats_timer_callback(void *arg) ++static bool reserve(subscription_t *s, target_t *t) + { +- // 直接调用 API 并广播 +- ts_api_result_t result = {0}; +- esp_err_t ret = ts_api_call("system.cpu", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- ts_ws_broadcast_to_topic("system.cpu", result.data); +- } ++ if (s_sequence == UINT64_MAX) { s_state=STOPPING; wake_locked(); return false; } /* fail closed, never reuse IDs */ ++ s->pending = ++s_sequence; ++ *t = (target_t){s->peer,s->revision,s->pending,s->topic}; ++ s_outstanding++; ++ return true; + } +- +-/* 定时器回调:Dashboard 聚合数据 */ +-static void dashboard_timer_callback(void *arg) ++static void submit(target_t t, ts_ws_message_t *m) + { +- // 创建聚合 JSON 对象 +- cJSON *dashboard = cJSON_CreateObject(); +- if (!dashboard) { +- TS_LOGE(TAG, "Failed to create dashboard JSON"); +- return; +- } +- +- ts_api_result_t result = {0}; +- esp_err_t ret; +- +- // 1. CPU 统计(高频数据) +- ret = ts_api_call("system.cpu", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "cpu", result.data); +- result.data = NULL; // 所有权转移,防止重复释放 +- } +- +- // 2. 内存信息 +- ret = ts_api_call("system.memory", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "memory", result.data); +- result.data = NULL; +- } +- +- // 3. 系统信息(uptime 等) +- ret = ts_api_call("system.info", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "info", result.data); +- result.data = NULL; +- } +- +- // 4. 网络状态 +- ret = ts_api_call("network.status", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "network", result.data); +- result.data = NULL; +- } +- +- // 5. 电源状态 +- ret = ts_api_call("power.status", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "power", result.data); +- result.data = NULL; +- } +- +- // 6. 风扇状态 +- ret = ts_api_call("fan.status", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "fan", result.data); +- result.data = NULL; +- } +- +- // 7. 服务列表 +- ret = ts_api_call("service.list", NULL, &result); +- if (ret == ESP_OK && result.code == 0 && result.data) { +- cJSON_AddItemToObject(dashboard, "services", result.data); +- result.data = NULL; +- } +- +- // 广播聚合数据(会复制一次数据) +- ts_ws_broadcast_to_topic("system.dashboard", dashboard); +- +- // 释放聚合对象(包含所有子对象) +- cJSON_Delete(dashboard); ++ esp_err_t ret = ESP_ERR_NO_MEM; ++ if (m && delivery_valid(t.revision,t.delivery)) ++ ret = ts_ws_transport_submit(t.peer,m,t.revision,t.delivery,delivery_valid,delivery_done); ++ if (ret != ESP_OK) delivery_done(t.revision,t.delivery,ret); ++ else { portENTER_CRITICAL(&s_lock); s_stats.queued++; portEXIT_CRITICAL(&s_lock); } + } +- +-/*===========================================================================*/ +-/* 公共 API */ +-/*===========================================================================*/ +- +-esp_err_t ts_ws_subscriptions_init(void) ++static bool metric_needed(target_t *targets, unsigned n, unsigned metric) + { +- if (s_subs_mutex) { +- return ESP_OK; // 已初始化 +- } +- +- // 创建互斥锁 +- s_subs_mutex = xSemaphoreCreateMutex(); +- if (!s_subs_mutex) { +- TS_LOGE(TAG, "Failed to create mutex"); +- return ESP_ERR_NO_MEM; +- } +- +- // 清空订阅数组 +- memset(s_subscriptions, 0, sizeof(s_subscriptions)); +- +- // 创建定时器(5秒间隔推送系统信息) +- esp_timer_create_args_t timer_args = { +- .callback = system_info_timer_callback, +- .name = "system_info_timer" +- }; +- esp_err_t ret = esp_timer_create(&timer_args, &s_system_info_timer); +- if (ret != ESP_OK) { +- TS_LOGE(TAG, "Failed to create system info timer: %s", esp_err_to_name(ret)); +- vSemaphoreDelete(s_subs_mutex); +- s_subs_mutex = NULL; +- return ret; +- } +- +- // 创建 CPU 统计定时器(1秒间隔) +- esp_timer_create_args_t cpu_timer_args = { +- .callback = cpu_stats_timer_callback, +- .name = "cpu_stats_timer" +- }; +- ret = esp_timer_create(&cpu_timer_args, &s_cpu_stats_timer); +- if (ret != ESP_OK) { +- TS_LOGE(TAG, "Failed to create CPU stats timer: %s", esp_err_to_name(ret)); +- esp_timer_delete(s_system_info_timer); +- vSemaphoreDelete(s_subs_mutex); +- s_subs_mutex = NULL; +- return ret; +- } +- +- // 创建 Dashboard 聚合定时器(1秒间隔) +- esp_timer_create_args_t dashboard_timer_args = { +- .callback = dashboard_timer_callback, +- .name = "dashboard_timer" +- }; +- ret = esp_timer_create(&dashboard_timer_args, &s_dashboard_timer); +- if (ret != ESP_OK) { +- TS_LOGE(TAG, "Failed to create dashboard timer: %s", esp_err_to_name(ret)); +- esp_timer_delete(s_cpu_stats_timer); +- esp_timer_delete(s_system_info_timer); +- vSemaphoreDelete(s_subs_mutex); +- s_subs_mutex = NULL; +- return ret; +- } +- +- TS_LOGI(TAG, "Subscription manager initialized"); +- return ESP_OK; ++ for (unsigned i=0;ifd = fd; +- strncpy(sub->topic, topic, MAX_TOPIC_LEN - 1); +- sub->topic[MAX_TOPIC_LEN - 1] = '\0'; +- sub->min_interval_ms = mapping->default_min_interval_ms; +- sub->last_broadcast_time = 0; +- sub->active = true; +- +- // 从参数中提取自定义间隔 +- if (params) { +- cJSON *interval = cJSON_GetObjectItem(params, "interval"); +- if (cJSON_IsNumber(interval) && interval->valueint > 0) { +- sub->min_interval_ms = interval->valueint; +- } +- } +- +- // 检查是否需要注册事件处理器(首个订阅该主题的客户端) +- int count = count_active_subscriptions(topic); +- bool first_subscriber = (count == 1); +- +- xSemaphoreGive(s_subs_mutex); +- +- if (first_subscriber) { +- // 注册事件处理器 +- ts_event_handler_handle_t *handle = NULL; +- void (*handler)(const ts_event_t *, void *) = NULL; +- +- if (strcmp(topic, "system.memory") == 0 || +- strcmp(topic, "network.status") == 0 || +- strcmp(topic, "power.status") == 0 || +- strcmp(topic, "fan.status") == 0 || +- strcmp(topic, "service.list") == 0) { +- handle = &s_system_event_handle; +- handler = system_event_handler; +- +- // 启动定时器(5秒间隔) +- if (s_system_info_timer && !esp_timer_is_active(s_system_info_timer)) { +- esp_timer_start_periodic(s_system_info_timer, 5000000); // 5秒 +- TS_LOGI(TAG, "Started system data timer (5s interval)"); ++ ts_ws_transport_flush(); ++ target_t targets[MAX_SUBSCRIPTIONS]; ++ unsigned n=0, capacity=ts_ws_message_capacity() ? ts_ws_transport_capacity() : 0; ++ int64_t now=esp_timer_get_time(); ++ portENTER_CRITICAL(&s_lock); ++ if(s_state==RUNNING) for(unsigned i=0;iactive && s->topic<8 && !s->pending && now>=s->next_attempt && reserve(s,&targets[n])) n++; ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if(n) { TS_WS_TEST_POINT("snapshot"); collect_batch(targets,n); } ++ /* Event FIFO per subscription. A slow target does not hold up other targets. ++ * Different operation results never overwrite each other. */ ++ for(unsigned slot=0;slotready) { ++ for(unsigned j=0;jtargets[j]) { ++ subscription_t *s=find_revision(e->targets[j]); ++ if(!s || s_state!=RUNNING) {e->targets[j]=0;continue;} ++ bool earlier=false; ++ for(unsigned k=0;korder) ++ for(unsigned l=0;lrevision) earlier=true; ++ if(!earlier && !s->pending && now>=s->next_attempt && ntargets[j]=0; ++ } + } +- } else if (strcmp(topic, "system.cpu") == 0) { +- // CPU 统计使用独立的 1秒定时器 +- if (s_cpu_stats_timer && !esp_timer_is_active(s_cpu_stats_timer)) { +- esp_timer_start_periodic(s_cpu_stats_timer, 1000000); // 1秒 +- TS_LOGI(TAG, "Started CPU stats timer (1s interval)"); +- } +- } else if (strcmp(topic, "system.dashboard") == 0) { +- // Dashboard 聚合订阅使用独立的 1秒定时器 +- if (s_dashboard_timer && !esp_timer_is_active(s_dashboard_timer)) { +- esp_timer_start_periodic(s_dashboard_timer, 1000000); // 1秒 +- TS_LOGI(TAG, "Started dashboard timer (1s interval)"); +- } +- } else if (strcmp(topic, "device.status") == 0) { +- handle = &s_device_event_handle; +- handler = device_event_handler; +- } else if (strcmp(topic, "ota.progress") == 0) { +- handle = &s_ota_event_handle; +- handler = ota_event_handler; ++ bool remaining=false; ++ for(unsigned j=0;jtargets[j]) remaining=true; ++ if(!remaining) {release=e->message; e->ready=false; /* held until submits finish */} + } +- +- if (handle && handler) { +- esp_err_t ret = ts_event_register( +- mapping->event_base, +- mapping->event_id, +- handler, +- NULL, +- handle +- ); +- if (ret == ESP_OK) { +- TS_LOGI(TAG, "Registered event handler for topic: %s", topic); +- } else { +- TS_LOGW(TAG, "Failed to register event handler: %s", esp_err_to_name(ret)); +- } ++ ts_ws_message_t *m=e->message; ++ portEXIT_CRITICAL(&s_lock); ++ for(unsigned j=0;jmin_interval_ms); +- return ESP_OK; + } +- +-esp_err_t ts_ws_unsubscribe(int fd, const char *topic) ++static TickType_t wait_ticks(int64_t delta) + { +- if (!topic || !s_subs_mutex) return ESP_ERR_INVALID_ARG; +- +- xSemaphoreTake(s_subs_mutex, portMAX_DELAY); +- +- // 查找并移除订阅 +- bool found = false; +- for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { +- if (s_subscriptions[i].active && +- s_subscriptions[i].fd == fd && +- strcmp(s_subscriptions[i].topic, topic) == 0) { +- s_subscriptions[i].active = false; +- found = true; +- break; +- } +- } +- +- // 检查是否需要取消注册事件处理器(最后一个订阅者离开) +- int count = count_active_subscriptions(topic); +- bool last_subscriber = (count == 0); +- +- xSemaphoreGive(s_subs_mutex); +- +- if (last_subscriber) { +- // 取消注册事件处理器 +- ts_event_handler_handle_t *handle = NULL; +- if (strcmp(topic, "system.memory") == 0 || +- strcmp(topic, "network.status") == 0 || +- strcmp(topic, "power.status") == 0 || +- strcmp(topic, "fan.status") == 0 || +- strcmp(topic, "service.list") == 0) { +- handle = &s_system_event_handle; +- +- // 检查是否还有其他 system.* 订阅 +- int system_subs = count_active_subscriptions("system.memory") + +- count_active_subscriptions("network.status") + +- count_active_subscriptions("power.status") + +- count_active_subscriptions("fan.status") + +- count_active_subscriptions("service.list"); +- +- // 如果所有 system.* topic 都没有订阅了,停止定时器 +- if (system_subs == 0 && s_system_info_timer) { +- esp_timer_stop(s_system_info_timer); +- TS_LOGI(TAG, "Stopped system data timer"); +- } +- } else if (strcmp(topic, "system.cpu") == 0) { +- // 停止 CPU 统计定时器 +- if (s_cpu_stats_timer && count_active_subscriptions("system.cpu") == 0) { +- esp_timer_stop(s_cpu_stats_timer); +- TS_LOGI(TAG, "Stopped CPU stats timer"); +- } +- } else if (strcmp(topic, "device.status") == 0) { +- handle = &s_device_event_handle; +- } else if (strcmp(topic, "ota.progress") == 0) { +- handle = &s_ota_event_handle; +- } +- +- if (handle && *handle) { +- ts_event_unregister(*handle); +- *handle = NULL; +- TS_LOGI(TAG, "Unregistered event handler for topic: %s", topic); +- } +- } +- +- if (found) { +- TS_LOGI(TAG, "Client %d unsubscribed from '%s'", fd, topic); +- } +- +- return found ? ESP_OK : ESP_ERR_NOT_FOUND; ++ if(delta<=0) return 1; ++ uint64_t tick_us=1000000/configTICK_RATE_HZ; ++ uint64_t ticks=((uint64_t)delta+tick_us-1)/tick_us; ++ if(ticks>=portMAX_DELAY) ticks=portMAX_DELAY-1; ++ return (TickType_t)ticks; + } +- +-void ts_ws_client_disconnected(int fd) ++static TickType_t next_wait(void) + { +- if (!s_subs_mutex) return; +- +- xSemaphoreTake(s_subs_mutex, portMAX_DELAY); +- +- // 移除该客户端的所有订阅 +- for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { +- if (s_subscriptions[i].active && s_subscriptions[i].fd == fd) { +- char topic[MAX_TOPIC_LEN]; +- strncpy(topic, s_subscriptions[i].topic, MAX_TOPIC_LEN); +- s_subscriptions[i].active = false; +- +- xSemaphoreGive(s_subs_mutex); +- ts_ws_unsubscribe(fd, topic); // 递归调用,处理事件取消注册 +- xSemaphoreTake(s_subs_mutex, portMAX_DELAY); +- } +- } +- +- xSemaphoreGive(s_subs_mutex); +- TS_LOGI(TAG, "Cleaned up subscriptions for client %d", fd); ++ if(ts_ws_transport_needs_flush()) return 1; ++ int64_t now=esp_timer_get_time(), nearest=INT64_MAX; ++ unsigned capacity=ts_ws_message_capacity() ? ts_ws_transport_capacity() : 0; ++ portENTER_CRITICAL(&s_lock); ++ for(unsigned i=0;iactive || s->pending) continue; ++ bool wanted=s->topic<8; ++ for(unsigned j=0;jrevision) wanted=true; ++ if(wanted && s->next_attemptnext_attempt; ++ } ++ if(nearest==INT64_MAX) s_stats.idle_wait++; ++ if(!capacity && nearest!=INT64_MAX) {nearest=after_ms(now,1000);s_stats.capacity_wait++;} ++ portEXIT_CRITICAL(&s_lock); ++ return nearest==INT64_MAX ? portMAX_DELAY : wait_ticks(nearest-now); + } +- +-void ts_ws_broadcast_to_topic(const char *topic, cJSON *data) ++static void telemetry_worker(void *arg) + { +- if (!topic || !data || !s_subs_mutex) return; +- +- xSemaphoreTake(s_subs_mutex, portMAX_DELAY); +- +- // 构造 WebSocket 消息 +- cJSON *msg = cJSON_CreateObject(); +- cJSON_AddStringToObject(msg, "type", "data"); +- cJSON_AddStringToObject(msg, "topic", topic); +- cJSON_AddItemToObject(msg, "data", cJSON_Duplicate(data, true)); +- cJSON_AddNumberToObject(msg, "timestamp", esp_timer_get_time() / 1000000); +- +- char *json_str = cJSON_PrintUnformatted(msg); +- cJSON_Delete(msg); +- +- if (!json_str) { +- xSemaphoreGive(s_subs_mutex); +- return; +- } +- +- // 遍历订阅,发送给符合条件的客户端 +- int sent_count = 0; +- for (int i = 0; i < MAX_SUBSCRIPTIONS; i++) { +- subscription_t *sub = &s_subscriptions[i]; +- if (!sub->active || strcmp(sub->topic, topic) != 0) { +- continue; +- } +- +- // 检查去抖动 +- if (!should_broadcast(sub)) { +- continue; ++ (void)arg; ++ for(;;) { ++ portENTER_CRITICAL(&s_lock); lifecycle_t state=s_state; portEXIT_CRITICAL(&s_lock); ++ if(state==STOPPING) break; ++ if(state==RUNNING) run_batch(); ++ uint32_t water=uxTaskGetStackHighWaterMark(NULL); ++ portENTER_CRITICAL(&s_lock);s_stats.stack_low_water=water;portEXIT_CRITICAL(&s_lock); ++ /* Notification arriving between deadline calculation and wait is retained. */ ++ ulTaskNotifyTake(pdTRUE,state==STARTING ? portMAX_DELAY : next_wait()); ++ } ++ /* Handle is invalidated under same lock used by every notifier. */ ++ portENTER_CRITICAL(&s_lock); s_worker=NULL; portEXIT_CRITICAL(&s_lock); ++ vTaskDelete(NULL); ++} ++static void event_handler(const ts_event_t *event, void *arg) ++{ ++ unsigned topic=(unsigned)(uintptr_t)arg; ++ bool demand=false; ++ portENTER_CRITICAL(&s_lock); ++ if(s_state==RUNNING) for(unsigned i=0;idata || !event->data_size) return; ++ /* Parse bounded event bytes, not an assumed NUL terminated buffer. */ ++ cJSON *data=cJSON_ParseWithLength(event->data,event->data_size); ++ if(data) {ts_ws_broadcast_to_topic(topics[topic].name,data);cJSON_Delete(data);} ++} ++esp_err_t ts_ws_subscriptions_init(void) ++{ ++ portENTER_CRITICAL(&s_lock); ++ if(s_state!=OFF) {esp_err_t ret=s_state==RUNNING?ESP_OK:ESP_ERR_INVALID_STATE;portEXIT_CRITICAL(&s_lock);return ret;} ++ s_state=STARTING; ++ portEXIT_CRITICAL(&s_lock); ++ const ts_event_base_t bases[]={TS_EVENT_BASE_SYSTEM,TS_EVENT_BASE_DEVICE_MON,TS_EVENT_BASE_OTA}; ++ const int ids[]={TS_EVENT_SYSTEM_INFO_CHANGED,TS_EVENT_DEVICE_STATUS_CHANGED,TS_EVENT_OTA_PROGRESS_UPDATE}; ++ const unsigned mapping[]={0,8,9}; ++ esp_err_t ret=ESP_OK; ++ for(unsigned i=0;i<3;i++) { ++ ret=ts_event_register(bases[i],ids[i],event_handler,(void*)(uintptr_t)mapping[i],&s_handlers[i]); ++ if(ret!=ESP_OK) break; ++ } ++ if(ret==ESP_OK && xTaskCreate(telemetry_worker,"ws_telemetry",WORKER_STACK,NULL,2,&s_worker)!=pdPASS) ret=ESP_ERR_NO_MEM; ++ portENTER_CRITICAL(&s_lock);s_state=ret==ESP_OK?RUNNING:STOPPING;wake_locked();portEXIT_CRITICAL(&s_lock); ++ if(ret!=ESP_OK) {esp_err_t cleanup=ts_ws_subscriptions_deinit();if(cleanup!=ESP_OK)return cleanup;} ++ return ret; ++} ++esp_err_t ts_ws_subscriptions_deinit(void) ++{ ++ if(ts_event_in_callback() || ts_ws_transport_in_context()) return ESP_ERR_INVALID_STATE; ++ portENTER_CRITICAL(&s_lock); ++ if(s_state==OFF) {portEXIT_CRITICAL(&s_lock);return ESP_OK;} ++ if(s_stop_owner || s_state==STARTING || s_worker==xTaskGetCurrentTaskHandle()) {portEXIT_CRITICAL(&s_lock);return ESP_ERR_INVALID_STATE;} ++ s_stop_owner=true;s_state=STOPPING; ++ for(unsigned i=0;i=deadline) {ret=ESP_ERR_TIMEOUT;goto done;} ++ vTaskDelay(1); ++ } ++ for(unsigned i=0;ivaluedouble; ++ if(!cJSON_IsNumber(p)||!isfinite(v)||v<0||v>UINT32_MAX||floor(v)!=v||(v==0 && id<8)) return ESP_ERR_INVALID_ARG; ++ interval=(uint32_t)v; ++ if(id<8 && intervalactive && s->topic==(unsigned)id && ts_ws_peer_equal(s->peer,peer)) {slot=s;break;} ++ if(!s->active && !slot) slot=s; ++ } ++ if(s_state==RUNNING && slot && s_sequence!=UINT64_MAX) { ++ if(!slot->active || slot->interval!=interval) { ++ int64_t last=slot->active?slot->last_success:0; ++ *slot=(subscription_t){.peer=peer,.revision=++s_sequence,.topic=id,.active=true, ++ .interval=interval,.last_success=last, ++ .next_attempt=id<8?after_ms(last?last:now,interval):now}; + } +- +- // 更新时间戳 +- sub->last_broadcast_time = esp_timer_get_time(); +- +- // 发送消息(异步) +- // 注意:这里需要从 ts_webui_ws.c 导出发送函数,或使用 broadcast +- // 暂时使用 broadcast API +- xSemaphoreGive(s_subs_mutex); +- ts_webui_broadcast(json_str); // TODO: 优化为只发送给订阅者 +- xSemaphoreTake(s_subs_mutex, portMAX_DELAY); +- +- sent_count++; +- } +- +- xSemaphoreGive(s_subs_mutex); +- +- if (sent_count > 0) { +- TS_LOGD(TAG, "Broadcasted to %d subscribers of '%s'", sent_count, topic); ++ ret=ESP_OK;wake_locked(); + } +- +- free(json_str); ++ portEXIT_CRITICAL(&s_lock);leave();return ret; ++} ++esp_err_t ts_ws_unsubscribe(ts_ws_peer_t peer,const char *topic) ++{ ++ int id=topic_id(topic);if(id<0)return ESP_ERR_NOT_FOUND; ++ if(!enter())return ESP_ERR_INVALID_STATE; ++ esp_err_t ret=ESP_ERR_NOT_FOUND; ++ portENTER_CRITICAL(&s_lock); ++ for(unsigned i=0;iused=true;e->order=++s_sequence; ++ bool any=false; ++ for(unsigned i=0;itargets[i]=s_subs[i].revision;any=true;} ++ if(!any) {e->used=false;e=NULL;} ++ } else s_stats.event_dropped++; ++ portEXIT_CRITICAL(&s_lock); ++ if(e) { ++ ts_ws_message_t *m=ts_ws_message_json(topic,data,esp_timer_get_time()/1000000); ++ portENTER_CRITICAL(&s_lock); ++ if(m) {e->message=m;e->ready=true;s_stats.serialized[id]++;wake_locked();} ++ else {memset(e,0,sizeof(*e));s_stats.event_dropped++;} ++ portEXIT_CRITICAL(&s_lock); ++ if(!m) TS_LOGW(TAG,"Topic event rejected: frame budget or allocation exhausted"); ++ } ++ leave(); + } +diff --git a/tests/prompts/ownership.browser.test.cjs b/tests/prompts/ownership.browser.test.cjs +index 0bea9b4..52510f7 100644 +--- a/tests/prompts/ownership.browser.test.cjs ++++ b/tests/prompts/ownership.browser.test.cjs +@@ -271,3 +271,33 @@ test('R1: delayed sign-out does not clear a newer sign-in',async()=>{ + });assert(r.clearedImmediately&&r.confirmed);assert.equal(r.token,'new'); + }finally{await context.close();} + }); ++ ++for (const language of ['zh-CN','en-US']) { ++ test(`WS protocol: actual page subscription class, independent intervals and acknowledgements ${language}`,async()=>{ ++ const first=await pageFor(language),second=await pageFor(language); ++ try { ++ await Promise.all([first.page.goto(base),second.page.goto(base)]); ++ await Promise.all([first.page.waitForFunction(()=>i18n.isReady()),second.page.waitForFunction(()=>i18n.isReady())]); ++ async function exercise(page,interval) { ++ return page.evaluate(interval=>{ ++ const sent=[],received=[]; ++ const mgr=new SubscriptionManager({send:message=>sent.push(message)}); ++ const callback=message=>received.push(message.data); ++ mgr.subscribe('system.cpu',callback,{interval}); ++ mgr.handleMessage({type:'subscribed',topic:'system.cpu',success:true}); ++ mgr.handleMessage({type:'data',topic:'system.cpu',data:{usage:12},timestamp:1}); ++ mgr.unsubscribe('system.cpu',callback); ++ mgr.handleMessage({type:'unsubscribed',topic:'system.cpu',success:true}); ++ mgr.handleMessage({type:'data',topic:'system.cpu',data:{usage:99},timestamp:2}); ++ return {sent,received,active:mgr.activeSubs.size}; ++ },interval); ++ } ++ const [a,b]=await Promise.all([exercise(first.page,1000),exercise(second.page,10000)]); ++ assert.equal(a.sent[0].params.interval,1000);assert.equal(b.sent[0].params.interval,10000); ++ for(const result of [a,b]) { ++ assert.deepEqual(result.received,[{usage:12}]);assert.equal(result.active,0); ++ assert.deepEqual(result.sent[1],{type:'unsubscribe',topic:'system.cpu'}); ++ } ++ }finally{await first.context.close();await second.context.close();} ++ }); ++} +diff --git a/components/ts_webui/include/ts_ws_transport.h b/components/ts_webui/include/ts_ws_transport.h +new file mode 100644 +index 0000000..e7b53d4 +--- /dev/null ++++ b/components/ts_webui/include/ts_ws_transport.h +@@ -0,0 +1,84 @@ ++#pragma once ++/* Internal bounded delivery path. Session mutation and send execute in HTTPD. */ ++#include "esp_http_server.h" ++#include "cJSON.h" ++#include ++#include ++#define TS_WS_TOPIC_TX_SLOTS 32 ++#define TS_WS_TX_SLOTS (TS_WS_TOPIC_TX_SLOTS + TS_WS_CONNECTIONS) ++#define TS_WS_MESSAGE_SLOTS 8 ++#define TS_WS_FRAME_BYTES 32768 ++#define TS_WS_LEGACY_BYTES (512 * 1024) ++#define TS_WS_TOTAL_BYTES (1024 * 1024) ++#ifdef CONFIG_TS_WEBUI_WS_MAX_CLIENTS ++#define TS_WS_CONNECTIONS CONFIG_TS_WEBUI_WS_MAX_CLIENTS ++#else ++#define TS_WS_CONNECTIONS 8 ++#endif ++ ++typedef struct { ++ httpd_handle_t server; ++ uint64_t epoch, connection; ++ int fd; ++} ts_ws_peer_t; ++typedef struct ts_ws_message ts_ws_message_t; ++typedef bool (*ts_ws_delivery_check_t)(uint64_t revision, uint64_t delivery); ++typedef void (*ts_ws_delivery_done_t)(uint64_t revision, uint64_t delivery, esp_err_t result); ++typedef void (*ts_ws_closed_t)(ts_ws_peer_t peer); ++esp_err_t ts_ws_transport_start(httpd_handle_t server, ts_ws_closed_t closed); ++esp_err_t ts_ws_transport_stop(httpd_handle_t server, uint32_t timeout_ms); ++bool ts_ws_transport_in_context(void); ++esp_err_t ts_ws_peer_open(httpd_req_t *req, ts_ws_peer_t *peer); ++/* HTTPD owner only. Values, not bare fd, cross task boundaries. */ ++void ts_ws_peer_close(ts_ws_peer_t peer); ++bool ts_ws_peer_get(httpd_handle_t server, int fd, ts_ws_peer_t *peer); ++bool ts_ws_peer_equal(ts_ws_peer_t a, ts_ws_peer_t b); ++unsigned ts_ws_transport_capacity(void); ++ts_ws_message_t *ts_ws_message_json(const char *topic, const cJSON *data, int64_t timestamp); ++ts_ws_message_t *ts_ws_message_text(const char *text, size_t len); ++void ts_ws_message_release(ts_ws_message_t *message); ++esp_err_t ts_ws_transport_submit(ts_ws_peer_t peer, ts_ws_message_t *message, ++ uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done); ++/* Compatibility bridge for existing global/stream senders; never coalesces. */ ++esp_err_t ts_ws_transport_send(httpd_handle_t server, int fd, const httpd_ws_frame_t *frame); ++ ++void ts_ws_transport_stopped(httpd_handle_t server); ++esp_err_t ts_ws_transport_broadcast(const httpd_ws_frame_t *frame); ++ ++void ts_ws_peer_log_level(ts_ws_peer_t peer, int level); ++esp_err_t ts_ws_transport_log(const httpd_ws_frame_t *frame, int level); ++unsigned ts_ws_message_capacity(void); ++ ++/* cJSON 1.7's AddItemReferenceToObject loses its newly allocated reference if ++ * key duplication fails. Own that reference explicitly; keys here are static. */ ++static inline bool ts_ws_json_reference(cJSON *object, const char *key, const cJSON *data) ++{ ++ if (!object || !data) return false; ++ cJSON *ref = cJSON_CreateNull(); ++ if (!ref) return false; ++ *ref = *data; ++ ref->next = ref->prev = NULL; ++ ref->string = NULL; ++ ref->type = (ref->type & ~cJSON_StringIsConst) | cJSON_IsReference; ++ if (cJSON_AddItemToObjectCS(object, key, ref)) return true; ++ cJSON_Delete(ref); ++ return false; ++} ++ ++typedef struct { ++ uint64_t queued, attempts, success, failed, stale, rejected; ++ uint32_t bytes, bytes_high, jobs, jobs_high; ++ int64_t max_send_us; ++} ts_ws_transport_stats_t; ++void ts_ws_transport_get_stats(ts_ws_transport_stats_t *stats); ++ ++/* Deterministic host barriers; compiled out in firmware. */ ++#ifndef TS_WS_TEST_POINT ++#define TS_WS_TEST_POINT(name) ((void)0) ++#endif ++ ++esp_err_t ts_ws_transport_quiesce(httpd_handle_t server, uint32_t timeout_ms); ++ ++void ts_ws_transport_flush(void); ++bool ts_ws_transport_needs_flush(void); ++void ts_ws_transport_cancel_topics(void); +diff --git a/components/ts_webui/src/ts_ws_transport.c b/components/ts_webui/src/ts_ws_transport.c +new file mode 100644 +index 0000000..e652895 +--- /dev/null ++++ b/components/ts_webui/src/ts_ws_transport.c +@@ -0,0 +1,466 @@ ++#include "ts_ws_transport.h" ++#include "esp_timer.h" ++#include "freertos/FreeRTOS.h" ++#include "freertos/task.h" ++#include ++#include ++#include ++ ++/* Stable control storage: no caller can race destruction of a mutex. No I/O, ++ * allocation, JSON operation or completion callback runs under this spinlock. */ ++static portMUX_TYPE s_lock = portMUX_INITIALIZER_UNLOCKED; ++static uint64_t s_sequence; ++static struct { ++ httpd_handle_t handle; ++ uint64_t epoch; ++ bool stopping, barrier_requested, quiesced, work_busy; ++ unsigned outstanding; ++ TaskHandle_t owner; ++ ts_ws_closed_t closed; ++} s_server; ++static ts_ws_peer_t s_peers[TS_WS_CONNECTIONS]; ++static int s_log_levels[TS_WS_CONNECTIONS]; ++struct ts_ws_message { unsigned refs; char *text; size_t len, capacity; }; ++static ts_ws_transport_stats_t s_tx_stats; ++static ts_ws_message_t s_messages[TS_WS_MESSAGE_SLOTS]; ++typedef enum {TX_FREE, TX_PREPARED, TX_QUEUED, TX_EXECUTING, TX_DONE, TX_CANCELED} tx_state_t; ++typedef struct { ++ unsigned refs; ++ tx_state_t state; ++ uint64_t order; ++ ts_ws_peer_t peer; ++ ts_ws_message_t *message; ++ uint64_t revision, delivery; ++ ts_ws_delivery_check_t check; ++ ts_ws_delivery_done_t done; ++} delivery_t; ++static delivery_t s_deliveries[TS_WS_TX_SLOTS]; ++static uint64_t s_delivery_order; ++extern void ts_ws_subscriptions_wake(void); ++ ++bool ts_ws_peer_equal(ts_ws_peer_t a, ts_ws_peer_t b) ++{ ++ return a.server == b.server && a.epoch == b.epoch && ++ a.fd == b.fd && a.connection == b.connection; ++} ++static bool peer_valid(ts_ws_peer_t peer) ++{ ++ if (s_server.stopping || s_server.handle != peer.server || s_server.epoch != peer.epoch) ++ return false; ++ for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) ++ if (s_peers[i].connection && ts_ws_peer_equal(s_peers[i], peer)) return true; ++ return false; ++} ++bool ts_ws_transport_in_context(void) ++{ ++ portENTER_CRITICAL(&s_lock); ++ bool same = s_server.owner && s_server.owner == xTaskGetCurrentTaskHandle(); ++ portEXIT_CRITICAL(&s_lock); ++ return same; ++} ++esp_err_t ts_ws_transport_start(httpd_handle_t server, ts_ws_closed_t closed) ++{ ++ if (!server) return ESP_ERR_INVALID_ARG; ++ portENTER_CRITICAL(&s_lock); ++ esp_err_t ret = ESP_ERR_INVALID_STATE; ++ if (!s_server.handle && s_sequence != UINT64_MAX) { ++ s_server.handle = server; ++ s_server.epoch = ++s_sequence; ++ s_server.closed = closed; ++ s_server.stopping = false; ++ ret = ESP_OK; ++ } ++ portEXIT_CRITICAL(&s_lock); ++ return ret; ++} ++bool ts_ws_peer_get(httpd_handle_t server, int fd, ts_ws_peer_t *peer) ++{ ++ bool found = false; ++ portENTER_CRITICAL(&s_lock); ++ for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) { ++ if (!s_server.stopping && s_peers[i].connection && s_peers[i].server == server && s_peers[i].fd == fd) { ++ *peer = s_peers[i]; found = true; break; ++ } ++ } ++ portEXIT_CRITICAL(&s_lock); ++ return found; ++} ++void ts_ws_peer_close(ts_ws_peer_t peer) ++{ ++ ts_ws_closed_t closed = NULL; ++ portENTER_CRITICAL(&s_lock); ++ for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) { ++ if (s_peers[i].connection && ts_ws_peer_equal(s_peers[i], peer)) { ++ s_peers[i].connection = 0; ++ closed = s_server.closed; ++ break; ++ } ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if (closed) closed(peer); ++} ++static void session_free(void *ctx) ++{ ++ ts_ws_peer_t *peer = ctx; ++ ts_ws_peer_close(*peer); ++ free(peer); ++} ++esp_err_t ts_ws_peer_open(httpd_req_t *req, ts_ws_peer_t *peer) ++{ ++ /* No authentication / TLS context is replaced. Current /ws owns no context. */ ++ if (req->sess_ctx) return ESP_ERR_INVALID_STATE; ++ ts_ws_peer_t *ctx = malloc(sizeof(*ctx)); ++ if (!ctx) return ESP_ERR_NO_MEM; ++ esp_err_t ret = ESP_ERR_NO_MEM; ++ portENTER_CRITICAL(&s_lock); ++ s_server.owner = xTaskGetCurrentTaskHandle(); ++ if (!s_server.stopping && req->handle == s_server.handle && s_sequence != UINT64_MAX) { ++ for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) if (!s_peers[i].connection) { ++ *ctx = (ts_ws_peer_t){req->handle, s_server.epoch, ++s_sequence, httpd_req_to_sockfd(req)}; ++ s_peers[i] = *ctx; s_log_levels[i] = -1; *peer = *ctx; ret = ESP_OK; break; ++ } ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if (ret != ESP_OK) { free(ctx); return ret; } ++ req->sess_ctx = ctx; ++ req->free_ctx = session_free; /* RST, LRU and httpd_stop also release this. */ ++ return ESP_OK; ++} ++static ts_ws_message_t *message_alloc(size_t capacity, bool telemetry) ++{ ++ ts_ws_message_t *m = NULL; ++ portENTER_CRITICAL(&s_lock); ++ for (unsigned i = telemetry ? 0 : TS_WS_MESSAGE_SLOTS - 2; capacity <= TS_WS_TOTAL_BYTES - s_tx_stats.bytes && ++ i < TS_WS_MESSAGE_SLOTS - (telemetry ? 2 : 0); ++i) if (!s_messages[i].refs) { ++ m = &s_messages[i]; m->refs = 1; m->capacity = capacity; ++ s_tx_stats.bytes += capacity; ++ if(s_tx_stats.bytes > s_tx_stats.bytes_high) s_tx_stats.bytes_high=s_tx_stats.bytes; ++ break; ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if (m) { ++ m->text = malloc(capacity); ++ if (!m->text) { ts_ws_message_release(m); return NULL; } ++ } ++ return m; ++} ++void ts_ws_message_release(ts_ws_message_t *m) ++{ ++ if (!m) return; ++ char *text = NULL; ++ bool reclaim = false; ++ portENTER_CRITICAL(&s_lock); ++ if (--m->refs == 0) { ++ /* Keep this slot and its byte reservation until free has completed. */ ++ m->refs = 1; ++ text = m->text; ++ reclaim = true; ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if (!reclaim) return; ++ free(text); ++ portENTER_CRITICAL(&s_lock); ++ m->text = NULL; ++ m->len = 0; ++ s_tx_stats.bytes -= m->capacity; ++ m->refs = 0; ++ portEXIT_CRITICAL(&s_lock); ++} ++ ++ts_ws_message_t *ts_ws_message_text(const char *text, size_t len) ++{ ++ if (!text || len >= TS_WS_LEGACY_BYTES) return NULL; ++ ts_ws_message_t *m = message_alloc(len + 1, false); ++ if (m) { memcpy(m->text, text, len); m->text[len] = 0; m->len = len; } ++ return m; ++} ++ts_ws_message_t *ts_ws_message_json(const char *topic, const cJSON *data, int64_t timestamp) ++{ ++ ts_ws_message_t *m = message_alloc(TS_WS_FRAME_BYTES, true); ++ if (!m) return NULL; ++ cJSON *root = cJSON_CreateObject(); ++ /* Reference is local to this call; bounded print copies before return. */ ++ bool ok = root && cJSON_AddStringToObject(root, "type", "data") && ++ cJSON_AddStringToObject(root, "topic", topic) && ++ cJSON_AddNumberToObject(root, "timestamp", timestamp) && ++ ts_ws_json_reference(root, "data", (cJSON *)data) && ++ cJSON_PrintPreallocated(root, m->text, TS_WS_FRAME_BYTES, false); ++ cJSON_Delete(root); ++ if (!ok) { ts_ws_message_release(m); return NULL; } ++ m->len = strlen(m->text); ++ return m; ++} ++unsigned ts_ws_transport_capacity(void) ++{ ++ unsigned n = 0; ++ portENTER_CRITICAL(&s_lock); ++ if (!s_server.stopping && s_server.handle) ++ for (unsigned i = 0; i < TS_WS_TOPIC_TX_SLOTS; ++i) n += !s_deliveries[i].refs; ++ portEXIT_CRITICAL(&s_lock); ++ return n; ++} ++static void delivery_release(delivery_t *d) ++{ ++ ts_ws_message_t *m = NULL; ++ portENTER_CRITICAL(&s_lock); ++ if (--d->refs == 0) { ++ m = d->message; ++ d->state=TX_FREE; ++ s_server.outstanding--; ++ s_tx_stats.jobs--; ++ } ++ portEXIT_CRITICAL(&s_lock); ++ ts_ws_message_release(m); ++} ++static void deliver(void *arg) ++{ ++ delivery_t *d = arg; ++ portENTER_CRITICAL(&s_lock); ++ s_server.owner = xTaskGetCurrentTaskHandle(); ++ d->state=TX_EXECUTING; ++ bool valid = peer_valid(d->peer); ++ portEXIT_CRITICAL(&s_lock); ++ esp_err_t ret = ESP_ERR_INVALID_STATE; ++ /* HTTPD session destruction/handshake/unsubscribe and this send are ordered ++ * on this same task. The stop owner keeps the server alive until refs drain. */ ++ if (valid && (!d->check || d->check(d->revision, d->delivery)) && ++ httpd_ws_get_fd_info(d->peer.server, d->peer.fd) == HTTPD_WS_CLIENT_WEBSOCKET) { ++ httpd_ws_frame_t frame = {.type = HTTPD_WS_TYPE_TEXT, ++ .payload = (uint8_t *)d->message->text, .len = d->message->len}; ++ int64_t start = esp_timer_get_time(); ++ ret = httpd_ws_send_frame_async(d->peer.server, d->peer.fd, &frame); ++ int64_t elapsed = esp_timer_get_time() - start; ++ portENTER_CRITICAL(&s_lock); ++ s_tx_stats.attempts++; ++ if(ret==ESP_OK) s_tx_stats.success++; else s_tx_stats.failed++; ++ if(elapsed>s_tx_stats.max_send_us) s_tx_stats.max_send_us=elapsed; ++ portEXIT_CRITICAL(&s_lock); ++ if (ret != ESP_OK) { ++ /* Owner context: invalidate this socket without taking over close() ++ * ownership. HTTPD will observe EOF and invoke the session hook. */ ++ shutdown(d->peer.fd, SHUT_RDWR); ++ ts_ws_peer_close(d->peer); ++ } ++ } else { ++ portENTER_CRITICAL(&s_lock); s_tx_stats.stale++; portEXIT_CRITICAL(&s_lock); ++ } ++ TS_WS_TEST_POINT("sent"); ++ if (d->done) d->done(d->revision, d->delivery, ret); ++ portENTER_CRITICAL(&s_lock); ++ d->state=TX_DONE; ++ s_server.work_busy=false; ++ portEXIT_CRITICAL(&s_lock); ++ delivery_release(d); ++ ts_ws_subscriptions_wake(); ++} ++/* One SDK control work item at a time. Accepted descriptors stay in our bounded ++ * FIFO, not the six-entry lwIP UDP control mailbox. Completion only wakes the ++ * telemetry worker; it never recursively queues another network operation. */ ++static esp_err_t publish_delivery(delivery_t *d) ++{ ++ esp_err_t ret=httpd_queue_work(d->peer.server,deliver,d); ++ portENTER_CRITICAL(&s_lock); ++ if(ret==ESP_OK)s_tx_stats.queued++; ++ else {s_tx_stats.rejected++;s_server.work_busy=false;d->state=TX_CANCELED;} ++ portEXIT_CRITICAL(&s_lock); ++ if(ret!=ESP_OK){ ++ if(d->done)d->done(d->revision,d->delivery,ret); ++ delivery_release(d); /* work reference */ ++ ts_ws_subscriptions_wake(); ++ } ++ delivery_release(d); /* publication reference, may outlive the callback */ ++ return ret; ++} ++void ts_ws_transport_flush(void) ++{ ++ delivery_t *next=NULL; ++ portENTER_CRITICAL(&s_lock); ++ if(!s_server.stopping && !s_server.work_busy) { ++ for(unsigned i=0;iorder))next=&s_deliveries[i]; ++ if(next){next->state=TX_QUEUED;next->refs++;s_server.work_busy=true;} ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if(next)publish_delivery(next); ++} ++bool ts_ws_transport_needs_flush(void) ++{ ++ bool ready=false; ++ portENTER_CRITICAL(&s_lock); ++ if(!s_server.stopping && !s_server.work_busy) ++ for(unsigned i=0;istate==TX_PREPARED && (!topics_only || d->done); ++ if(cancel){d->state=TX_CANCELED;s_tx_stats.stale++;} /* take its existing work reference */ ++ portEXIT_CRITICAL(&s_lock); ++ if(cancel){if(d->done)d->done(d->revision,d->delivery,ESP_ERR_INVALID_STATE);delivery_release(d);} ++ } ++} ++void ts_ws_transport_cancel_topics(void){cancel_ready(true);} ++esp_err_t ts_ws_transport_submit(ts_ws_peer_t peer, ts_ws_message_t *message, ++ uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done) ++{ ++ if(!message)return ESP_ERR_INVALID_ARG; ++ delivery_t *d=NULL; ++ portENTER_CRITICAL(&s_lock); ++ if(peer_valid(peer) && s_delivery_order!=UINT64_MAX) ++ for(unsigned i=done?0:TS_WS_TOPIC_TX_SLOTS;i<(done?TS_WS_TOPIC_TX_SLOTS:TS_WS_TX_SLOTS);i++)if(!s_deliveries[i].refs){ ++ d=&s_deliveries[i]; ++ *d=(delivery_t){.refs=2,.state=TX_PREPARED,.order=++s_delivery_order,.peer=peer, ++ .message=message,.revision=revision,.delivery=delivery,.check=check,.done=done}; ++ message->refs++;s_server.outstanding++;s_tx_stats.jobs++; ++ if(s_tx_stats.jobs>s_tx_stats.jobs_high)s_tx_stats.jobs_high=s_tx_stats.jobs; ++ break; ++ } ++ if(!d)s_tx_stats.rejected++; ++ portEXIT_CRITICAL(&s_lock); ++ if(!d)return ESP_ERR_NO_MEM; ++ /* Accepted into the local FIFO. Queue/send failures are settled through done, ++ * exactly once. The producer reference prevents early completion reuse. */ ++ ts_ws_transport_flush(); ++ delivery_release(d); ++ ts_ws_subscriptions_wake(); ++ return ESP_OK; ++} ++esp_err_t ts_ws_transport_send(httpd_handle_t server, int fd, const httpd_ws_frame_t *frame) ++{ ++ ts_ws_peer_t peer; ++ if (!ts_ws_peer_get(server, fd, &peer)) return ESP_ERR_INVALID_STATE; ++ if(ts_ws_transport_in_context()) { ++ /* Current HTTP request owns the session until it returns; HTTPD stop ++ * waits for that request. Keep synchronous terminal takeover ordering. */ ++ return httpd_ws_send_frame_async(server,fd,(httpd_ws_frame_t *)frame); ++ } ++ ts_ws_message_t *m = ts_ws_message_text((const char *)frame->payload, frame->len); ++ if (!m) return ESP_ERR_NO_MEM; ++ esp_err_t ret = ts_ws_transport_submit(peer, m, 0, 0, NULL, NULL); ++ ts_ws_message_release(m); ++ return ret; ++} ++esp_err_t ts_ws_transport_stop(httpd_handle_t server, uint32_t timeout_ms) ++{ ++ if (ts_ws_transport_in_context()) return ESP_ERR_INVALID_STATE; ++ int64_t now = esp_timer_get_time(), delta = (int64_t)timeout_ms * 1000; ++ int64_t deadline = now > INT64_MAX - delta ? INT64_MAX : now + delta; ++ for (;;) { ++ portENTER_CRITICAL(&s_lock); ++ if (!s_server.handle) { portEXIT_CRITICAL(&s_lock); return ESP_OK; } ++ if (server != s_server.handle) { portEXIT_CRITICAL(&s_lock); return ESP_ERR_INVALID_ARG; } ++ s_server.stopping = true; ++ portEXIT_CRITICAL(&s_lock); ++ cancel_ready(false); ++ portENTER_CRITICAL(&s_lock); ++ unsigned outstanding=s_server.outstanding; ++ portEXIT_CRITICAL(&s_lock); ++ if (!outstanding) return ESP_OK; ++ if (esp_timer_get_time() >= deadline) return ESP_ERR_TIMEOUT; ++ vTaskDelay(1); ++ } ++} ++/* Called only after actual HTTPD stop has freed all sessions. */ ++void ts_ws_transport_stopped(httpd_handle_t server) ++{ ++ portENTER_CRITICAL(&s_lock); ++ if (s_server.handle == server && s_server.stopping && !s_server.outstanding) { ++ memset(&s_server, 0, sizeof(s_server)); ++ memset(s_peers, 0, sizeof(s_peers)); ++ } ++ portEXIT_CRITICAL(&s_lock); ++} ++ ++static bool log_allowed(uint64_t connection, uint64_t level) ++{ ++ bool allowed=false; ++ portENTER_CRITICAL(&s_lock); ++ for(unsigned i=0;i=0 && level<=(unsigned)s_log_levels[i]) allowed=true; ++ portEXIT_CRITICAL(&s_lock); ++ return allowed; ++} ++static esp_err_t broadcast_filtered(const httpd_ws_frame_t *frame, int level) ++{ ++ ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ unsigned n=0; ++ portENTER_CRITICAL(&s_lock); ++ if(!s_server.stopping) for(unsigned i=0;ipayload,frame->len); ++ if(!m) return ESP_ERR_NO_MEM; ++ esp_err_t ret=ESP_OK; ++ for(unsigned i=0;i= (int64_t)timeout_ms*1000)return ESP_ERR_TIMEOUT; ++ vTaskDelay(1); ++ } ++} +diff --git a/tests/ws_subscriptions/README.md b/tests/ws_subscriptions/README.md +new file mode 100644 +index 0000000..cbf7aac +--- /dev/null ++++ b/tests/ws_subscriptions/README.md +@@ -0,0 +1,19 @@ ++# WebSocket host regressions ++ ++Run from the repository root: ++ ++```sh ++./tests/ws_subscriptions/run_baseline.sh ++./tests/ws_subscriptions/run_host.sh ++``` ++ ++`IDF_PATH` selects the SDK cJSON source; the local fallback is the existing ESP-IDF v5.5.2 installation. No device, socket server, firmware write, remote operation or git mutation is performed. ++ ++- Baseline script obtains the pinned historical **source and header** using `git show`, compiles them in a temporary directory, and expects business assertions to fail. T02/T05 execute the original dashboard callback; T07 counts actual calls to the global broadcast boundary (the 3-client fanout is an explicitly labelled boundary calculation). The event test runs the original dispatcher and ASan detects its self-unregister UAF. The current checkout is never replaced. ++- Manager test compiles/includes the entire current `ts_ws_subscriptions.c` and `ts_ws_transport.c`, plus SDK cJSON. Only platform boundaries are replaced. No duplicated scheduler / delivery implementation is used. ++- Clock and HTTPD execution are deterministic. Worker entry is real C, but the host does not emulate full FreeRTOS scheduling. Four barriers (snapshot, API, queued work, send-before-completion) each exercise cancellation, resubscription, disconnect, fd reuse and stop/restart exclusion. The current in-flight frame is allowed to finish at the final barrier. ++- Event test compiles/includes current `ts_event.c`, using real pthread mutex/condition barriers for concurrent dispatch/unregister. It covers self-unregister, retiring another selected node, synchronous drain, timeout/retry, and unrelated handlers. ASan/UBSan are enabled. TSan was also run separately on this event test; that is not a TSan proof of the mocked RTOS scheduler. ++- Lifecycle tests extract the unmodified bodies of production WebSocket init/stop and HTTP/WebUI stop/deinit/status functions at test time; HTTPD stop and hooks are controlled boundaries. They verify actual failure propagation and route-copy ownership, not a logic copy. ++- The 32-service escaped-name payload is a size stress fixture for the production serializer, not a replacement implementation of the service API. The 512 KiB legacy-frame boundary and total bytes / descriptor ceilings are tested separately. ++ ++Mock success of `httpd_ws_send_frame_async` means only success at that API boundary. It is not proof of browser delivery, TCP timing, device heap, CPU utilization, or stack high-water on ESP32-S3. See `docs/repair/ws-subscriptions/README.md` for the acceptance matrix and device checklist. +diff --git a/tests/ws_subscriptions/run_baseline.sh b/tests/ws_subscriptions/run_baseline.sh +new file mode 100755 +index 0000000..93ac5be +--- /dev/null ++++ b/tests/ws_subscriptions/run_baseline.sh +@@ -0,0 +1,29 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++build=$(mktemp -d /tmp/ts-ws-baseline.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++# Fixed evidence baseline only. Never overwrites the working tree. ++git show 35238b4645ae5e9e0e99555d4fb64080d945565c:components/ts_webui/src/ts_ws_subscriptions.c > "$build/ts_ws_subscriptions.c" ++git show 35238b4645ae5e9e0e99555d4fb64080d945565c:components/ts_webui/include/ts_ws_subscriptions.h > "$build/ts_ws_subscriptions.h" ++cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" ++export DEVELOPER_DIR=/Library/Developer/CommandLineTools ++cc -Wno-deprecated-declarations -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -I"$build" -Icomponents/ts_webui/include -I"$cjson" tests/ws_subscriptions/test_baseline.c "$cjson/cJSON.c" -o "$build/test" ++for case in T02 T05 T07; do ++ set +e ++ ASAN_OPTIONS=detect_leaks=0 "$build/test" "$case" ++ result=$? ++ set -e ++ if [ "$result" != 1 ]; then echo "Unexpected baseline outcome $result"; exit 2; fi ++ echo "Expected business assertion failure: $case" ++done ++ ++git show 35238b4645ae5e9e0e99555d4fb64080d945565c:components/ts_core/ts_event/src/ts_event.c > "$build/ts_event.c" ++cc -std=gnu11 -DBASELINE_EVENT -g -fsanitize=address,undefined -I"$build" -Icomponents/ts_core/ts_event/include -Itests/ws_subscriptions/stubs -I"$cjson" tests/ws_subscriptions/test_event.c -o "$build/event" ++set +e ++"$build/event" > "$build/event.log" 2>&1 ++result=$? ++set -e ++if [ "$result" = 0 ] || ! rg -q 'heap-use-after-free' "$build/event.log"; then cat "$build/event.log"; exit 2; fi ++rg -m 1 'ERROR: AddressSanitizer:' "$build/event.log" ++echo 'Expected T32 baseline failure: actual dispatch accesses self-unregistered freed node' +diff --git a/tests/ws_subscriptions/run_host.sh b/tests/ws_subscriptions/run_host.sh +new file mode 100755 +index 0000000..f3971e8 +--- /dev/null ++++ b/tests/ws_subscriptions/run_host.sh +@@ -0,0 +1,40 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++build=$(mktemp -d /tmp/ts-ws-host.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++export DEVELOPER_DIR=/Library/Developer/CommandLineTools ++cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" ++cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" tests/ws_subscriptions/test_manager.c "$cjson/cJSON.c" -o "$build/manager" ++"$build/manager" ++cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Icomponents/ts_core/ts_event/include -Itests/ws_subscriptions/stubs -Icomponents/ts_core/ts_event/src -I"$cjson" tests/ws_subscriptions/test_event.c -o "$build/event" ++"$build/event" ++python3 - "$build" <<'PY' ++from pathlib import Path ++import re,sys ++for source,names,out in [ ++ ('components/ts_net/src/ts_http_server.c',['ts_http_server_stop','ts_http_server_deinit'],'http_stop.inc'), ++ ('components/ts_webui/src/ts_webui.c',['ts_webui_stop','ts_webui_deinit','ts_webui_is_running'],'webui_stop.inc')]: ++ s=Path(source).read_text();parts=[] ++ for name in names: ++ m=re.search(r'^(?:esp_err_t|bool) '+name+r'\(void\)\s*\{',s,re.M);assert m,name ++ parts.append(s[m.start():s.index('\n}',m.start())+2]) ++ Path(sys.argv[1],out).write_text('\n'.join(parts)) ++PY ++cc -std=gnu11 -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -I"$cjson" -I"$build" tests/ws_subscriptions/test_lifecycle.c -o "$build/lifecycle" ++"$build/lifecycle" ++python3 - "$build" <<'PY' ++from pathlib import Path ++import sys ++s=Path('components/ts_webui/src/ts_webui_ws.c').read_text() ++a=s.index('esp_err_t ts_webui_ws_init(void)');b=s.index('\n}',a)+2 ++Path(sys.argv[1],'ws_init.inc').write_text(s[a:b]) ++a=s.index('esp_err_t ts_webui_ws_stop(httpd_handle_t server)\n{');b=s.index('\n}',a)+2 ++Path(sys.argv[1],'ws_stop.inc').write_text(s[a:b]) ++parts=[] ++for name in ['ts_webui_ssh_exec_start','ts_webui_ssh_exec_start_ex']: ++ a=s.index('esp_err_t '+name+'(');b=s.index('\n}',a)+2;parts.append(s[a:b]) ++Path(sys.argv[1],'ws_creators.inc').write_text('\n'.join(parts)) ++PY ++cc -std=gnu11 -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -I"$cjson" -I"$build" tests/ws_subscriptions/test_init.c -o "$build/init" ++"$build/init" +diff --git a/tests/ws_subscriptions/stubs/esp_err.h b/tests/ws_subscriptions/stubs/esp_err.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/esp_err.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/esp_heap_caps.h b/tests/ws_subscriptions/stubs/esp_heap_caps.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/esp_heap_caps.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/esp_http_server.h b/tests/ws_subscriptions/stubs/esp_http_server.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/esp_http_server.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/esp_log.h b/tests/ws_subscriptions/stubs/esp_log.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/esp_log.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/esp_timer.h b/tests/ws_subscriptions/stubs/esp_timer.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/esp_timer.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/freertos/FreeRTOS.h b/tests/ws_subscriptions/stubs/freertos/FreeRTOS.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/freertos/FreeRTOS.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/freertos/queue.h b/tests/ws_subscriptions/stubs/freertos/queue.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/freertos/queue.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/freertos/semphr.h b/tests/ws_subscriptions/stubs/freertos/semphr.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/freertos/semphr.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/freertos/task.h b/tests/ws_subscriptions/stubs/freertos/task.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/freertos/task.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/platform.h b/tests/ws_subscriptions/stubs/platform.h +new file mode 100644 +index 0000000..25b7b31 +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/platform.h +@@ -0,0 +1,119 @@ ++#pragma once ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "cJSON.h" ++typedef int esp_err_t; ++#define ESP_OK 0 ++#define ESP_FAIL -1 ++#define ESP_ERR_NO_MEM 0x101 ++#define ESP_ERR_INVALID_ARG 0x102 ++#define ESP_ERR_INVALID_STATE 0x103 ++#define ESP_ERR_INVALID_SIZE 0x104 ++#define ESP_ERR_NOT_FOUND 0x105 ++#define ESP_ERR_TIMEOUT 0x106 ++#define ESP_ERR_NOT_SUPPORTED 0x107 ++#define TS_LOGD(...) ((void)0) ++#define TS_LOGI(...) ((void)0) ++#define TS_LOGW(...) ((void)0) ++#define TS_LOGE(...) ((void)0) ++#define portMAX_DELAY UINT32_MAX ++#define pdTRUE 1 ++#define pdPASS 1 ++#define pdMS_TO_TICKS(ms) (ms) ++#define portTICK_PERIOD_MS 1 ++#define configTICK_RATE_HZ 1000 ++typedef unsigned TickType_t; ++typedef int BaseType_t; ++typedef unsigned UBaseType_t; ++typedef pthread_mutex_t portMUX_TYPE; ++#define portMUX_INITIALIZER_UNLOCKED PTHREAD_MUTEX_INITIALIZER ++#define portENTER_CRITICAL(p) pthread_mutex_lock(p) ++#define portEXIT_CRITICAL(p) pthread_mutex_unlock(p) ++typedef pthread_mutex_t *SemaphoreHandle_t; ++static inline SemaphoreHandle_t xSemaphoreCreateMutex(void) { SemaphoreHandle_t p=malloc(sizeof(*p)); pthread_mutex_init(p,0); return p; } ++static inline int xSemaphoreTake(SemaphoreHandle_t p,unsigned t) { (void)t; return !pthread_mutex_lock(p); } ++static inline int xSemaphoreGive(SemaphoreHandle_t p) { return !pthread_mutex_unlock(p); } ++static inline void vSemaphoreDelete(SemaphoreHandle_t p) { pthread_mutex_destroy(p);free(p); } ++static inline const char *esp_err_to_name(int e) {(void)e;return "error";} ++extern int64_t test_now; ++static inline int64_t esp_timer_get_time(void) {return test_now;} ++typedef struct test_timer {void (*callback)(void*); bool active;} *esp_timer_handle_t; ++typedef struct {void (*callback)(void*);const char*name;} esp_timer_create_args_t; ++static inline int esp_timer_create(const esp_timer_create_args_t*a,esp_timer_handle_t*p) {*p=calloc(1,sizeof(**p));(*p)->callback=a->callback;return 0;} ++static inline int esp_timer_start_periodic(esp_timer_handle_t p,uint64_t us) {(void)us;p->active=true;return 0;} ++static inline int esp_timer_stop(esp_timer_handle_t p) {p->active=false;return 0;} ++static inline int esp_timer_delete(esp_timer_handle_t p) {free(p);return 0;} ++static inline bool esp_timer_is_active(esp_timer_handle_t p) {return p->active;} ++#ifndef TEST_REAL_EVENT ++typedef const char *ts_event_base_t; ++typedef void *ts_event_handler_handle_t; ++typedef struct {void*data;size_t data_size;} ts_event_t; ++#define TS_EVENT_BASE_SYSTEM "system" ++#define TS_EVENT_BASE_DEVICE_MON "device" ++#define TS_EVENT_BASE_OTA "ota" ++#define TS_EVENT_SYSTEM_INFO_CHANGED 1 ++#define TS_EVENT_DEVICE_STATUS_CHANGED 2 ++#define TS_EVENT_OTA_PROGRESS_UPDATE 3 ++#ifdef TEST_FAIL_EVENTS ++extern int test_event_fail_at, test_event_registers; ++#endif ++static inline int ts_event_register(const char*b,int i,void(*h)(const ts_event_t*,void*),void*u,void**out) {(void)b;(void)i;(void)h;(void)u; ++#ifdef TEST_FAIL_EVENTS ++if(++test_event_registers==test_event_fail_at)return ESP_ERR_NO_MEM; ++#endif ++*out=(void*)1;return 0;} ++static inline int ts_event_unregister(void*h) {(void)h;return 0;} ++static inline int ts_event_post(const char*b,int i,const void*d,size_t s,unsigned t) {(void)b;(void)i;(void)d;(void)s;(void)t;return 0;} ++#endif ++typedef struct {int code;cJSON*data;char*message;} ts_api_result_t; ++int ts_api_call(const char*,const cJSON*,ts_api_result_t*); ++#ifdef TEST_ALLOC ++extern int test_result_frees; ++#endif ++static inline void ts_api_result_free(ts_api_result_t*r) { ++#ifdef TEST_ALLOC ++test_result_frees++; ++#endif ++cJSON_Delete(r->data);free(r->message);memset(r,0,sizeof(*r));} ++int ts_webui_broadcast(const char*); ++typedef void *TaskHandle_t; ++TaskHandle_t xTaskGetCurrentTaskHandle(void); ++int xTaskCreate(void(*fn)(void*),const char*,unsigned,void*,unsigned,TaskHandle_t*); ++void xTaskNotifyGive(TaskHandle_t); ++unsigned ulTaskNotifyTake(int,TickType_t); ++void vTaskDelete(TaskHandle_t); ++void vTaskDelay(TickType_t); ++#ifndef TEST_REAL_EVENT ++static inline bool ts_event_in_callback(void) {return false;} ++static inline int ts_event_unregister_sync(void*h,unsigned t) {(void)h;(void)t;return 0;} ++#endif ++typedef void *httpd_handle_t; ++typedef struct {httpd_handle_t handle;void*sess_ctx;void(*free_ctx)(void*);int fd;} httpd_req_t; ++typedef struct {int type;uint8_t*payload;size_t len;} httpd_ws_frame_t; ++#define HTTPD_WS_TYPE_TEXT 1 ++#define HTTPD_WS_CLIENT_WEBSOCKET 2 ++static inline int httpd_req_to_sockfd(httpd_req_t*r) {return r->fd;} ++int httpd_ws_get_fd_info(httpd_handle_t,int); ++int httpd_ws_send_frame_async(httpd_handle_t,int,httpd_ws_frame_t*); ++int httpd_queue_work(httpd_handle_t,void(*)(void*),void*); ++#define ESP_LOGI(...) ((void)0) ++#define ESP_LOGD(...) ((void)0) ++#define ESP_LOGW(...) ((void)0) ++#define ESP_LOGE(...) ((void)0) ++#define MALLOC_CAP_SPIRAM 1 ++#define MALLOC_CAP_8BIT 2 ++static inline void*heap_caps_calloc(size_t n,size_t s,unsigned c) {(void)c;return calloc(n,s);} ++typedef void*QueueHandle_t; ++static inline QueueHandle_t xQueueCreate(unsigned n,unsigned s) {(void)n;(void)s;return malloc(1);} ++static inline void vQueueDelete(void*p) {free(p);} ++static inline int xQueueSend(void*q,const void*d,unsigned t) {(void)q;(void)d;(void)t;return pdTRUE;} ++static inline int xQueueSendFromISR(void*q,const void*d,int*t) {(void)q;(void)d;(void)t;return pdTRUE;} ++static inline int xQueueReceive(void*q,void*d,unsigned t) {(void)q;(void)d;(void)t;return 0;} ++static inline unsigned uxQueueMessagesWaiting(void*q) {(void)q;return 0;} ++ ++static inline unsigned uxTaskGetStackHighWaterMark(TaskHandle_t t){(void)t;return 8192;} +diff --git a/tests/ws_subscriptions/stubs/ts_api.h b/tests/ws_subscriptions/stubs/ts_api.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/ts_api.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/ts_event.h b/tests/ws_subscriptions/stubs/ts_event.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/ts_event.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/ts_log.h b/tests/ws_subscriptions/stubs/ts_log.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/ts_log.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/stubs/ts_webui.h b/tests/ws_subscriptions/stubs/ts_webui.h +new file mode 100644 +index 0000000..948df4b +--- /dev/null ++++ b/tests/ws_subscriptions/stubs/ts_webui.h +@@ -0,0 +1 @@ ++#include "platform.h" +diff --git a/tests/ws_subscriptions/test_baseline.c b/tests/ws_subscriptions/test_baseline.c +new file mode 100644 +index 0000000..fbbafa4 +--- /dev/null ++++ b/tests/ws_subscriptions/test_baseline.c +@@ -0,0 +1,25 @@ ++#include "platform.h" ++#include "ts_ws_subscriptions.c" ++int64_t test_now=10000000; ++static int reads,broadcasts; ++int ts_api_call(const char*m,const cJSON*p,ts_api_result_t*r) {(void)m;(void)p;reads++;r->code=0;r->data=cJSON_CreateObject();return 0;} ++int ts_webui_broadcast(const char*s) {(void)s;broadcasts++;return 0;} ++int main(int argc,char**argv) { ++ assert(argc==2);assert(ts_ws_subscriptions_init()==0); ++ cJSON*p=cJSON_Parse("{\"interval\":10000}"); ++ ts_ws_subscribe(1,"system.dashboard",p);cJSON_Delete(p); ++ if (!strcmp(argv[1],"T02")) { ++ ts_ws_unsubscribe(1,"system.dashboard"); ++ if(s_dashboard_timer->active)s_dashboard_timer->callback(NULL); ++ printf("T02 no subscribers: API reads=%d (expected 0)\n",reads);return reads?1:0; ++ } ++ if (!strcmp(argv[1],"T05")) { ++ dashboard_timer_callback(NULL);reads=0;test_now+=1000000; ++ dashboard_timer_callback(NULL); ++ printf("T05 before next deadline: API reads=%d (expected 0)\n",reads);return reads?1:0; ++ } ++ ts_ws_subscribe(2,"system.dashboard",NULL); ++ cJSON*d=cJSON_CreateObject();ts_ws_broadcast_to_topic("system.dashboard",d);cJSON_Delete(d); ++ printf("T06/T07 2 targets, 3 connected: global broadcast calls=%d => %d frames (expected 2 targeted frames)\n",broadcasts,broadcasts*3); ++ return broadcasts?1:0; ++} +diff --git a/tests/ws_subscriptions/test_event.c b/tests/ws_subscriptions/test_event.c +new file mode 100644 +index 0000000..878078b +--- /dev/null ++++ b/tests/ws_subscriptions/test_event.c +@@ -0,0 +1,59 @@ ++#define TEST_REAL_EVENT ++#include "platform.h" ++#include ++#include "ts_event.c" ++int64_t test_now; ++TaskHandle_t xTaskGetCurrentTaskHandle(void) {return (void*)pthread_self();} ++int xTaskCreate(void(*fn)(void*),const char*n,unsigned s,void*a,unsigned p,TaskHandle_t*out) {(void)fn;(void)n;(void)s;(void)a;(void)p;*out=(void*)1;return pdPASS;} ++void vTaskDelete(TaskHandle_t t) {(void)t;} ++static pthread_mutex_t barrier=PTHREAD_MUTEX_INITIALIZER; ++static pthread_cond_t cv=PTHREAD_COND_INITIALIZER; ++static bool entered, release_callback, drain_waiting; ++static atomic_bool drained; ++void vTaskDelay(TickType_t t) {(void)t;pthread_mutex_lock(&barrier);drain_waiting=true;pthread_cond_broadcast(&cv);pthread_mutex_unlock(&barrier);sched_yield();} ++static ts_event_handler_handle_t self_handle, blocked_handle, other_handle; ++static int other_calls,self_calls; ++static void self_cancel(const ts_event_t*e,void*u) {(void)e;(void)u;self_calls++;assert(ts_event_unregister(self_handle)==0);} ++static void other(const ts_event_t*e,void*u) {(void)e;(void)u;other_calls++;} ++static void blocked(const ts_event_t*e,void*u) {(void)e;(void)u; ++#ifndef BASELINE_EVENT ++ assert(ts_event_unregister_sync(blocked_handle,10)==ESP_ERR_INVALID_STATE); ++#endif ++ pthread_mutex_lock(&barrier);entered=true;pthread_cond_broadcast(&cv);while(!release_callback)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier); ++} ++static void*post(void*p) {(void)p;ts_event_post_sync("test",1,NULL,0);return NULL;} ++#ifndef BASELINE_EVENT ++static void*drain(void*p) {(void)p;assert(ts_event_unregister_sync(blocked_handle,100)==0);drained=true;return NULL;} ++#endif ++int main(void) { ++ s_event_ctx.initialized=true;s_event_ctx.running=true;s_event_ctx.mutex=xSemaphoreCreateMutex(); ++ assert(ts_event_register("test",1,self_cancel,NULL,&self_handle)==0); ++ ts_event_post_sync("test",1,NULL,0);assert(self_calls==1); ++ assert(ts_event_register("test",1,other,NULL,&other_handle)==0); ++ assert(ts_event_register("test",1,blocked,NULL,&blocked_handle)==0); ++ pthread_t dispatch;pthread_create(&dispatch,NULL,post,NULL); ++ pthread_mutex_lock(&barrier);while(!entered)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier); ++ assert(ts_event_unregister(other_handle)==0); /* selected snapshot but not yet invoked */ ++#ifndef BASELINE_EVENT ++ pthread_t waiter;pthread_create(&waiter,NULL,drain,NULL); ++ pthread_mutex_lock(&barrier);while(!drain_waiting)pthread_cond_wait(&cv,&barrier);assert(!drained);release_callback=true;pthread_cond_broadcast(&cv);pthread_mutex_unlock(&barrier); ++ pthread_join(waiter,NULL);assert(drained); ++#else ++ ts_event_unregister(blocked_handle); ++ pthread_mutex_lock(&barrier);release_callback=true;pthread_cond_broadcast(&cv);pthread_mutex_unlock(&barrier); ++#endif ++ pthread_join(dispatch,NULL);assert(other_calls==0);assert(!s_event_ctx.handlers); ++ assert(ts_event_register("test",1,other,NULL,&other_handle)==0);ts_event_post_sync("test",1,NULL,0);assert(other_calls==1);assert(ts_event_unregister(other_handle)==0); ++#ifndef BASELINE_EVENT ++ entered=false;release_callback=false; ++ assert(ts_event_register("test",1,blocked,NULL,&blocked_handle)==0); ++ pthread_create(&dispatch,NULL,post,NULL); ++ pthread_mutex_lock(&barrier);while(!entered)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier); ++ assert(ts_event_unregister_sync(blocked_handle,0)==ESP_ERR_TIMEOUT); ++ pthread_mutex_lock(&barrier);release_callback=true;pthread_cond_broadcast(&cv);pthread_mutex_unlock(&barrier); ++ pthread_join(dispatch,NULL);assert(s_event_ctx.handlers); /* retained for drain retry */ ++ assert(ts_event_unregister_sync(blocked_handle,0)==0);assert(!s_event_ctx.handlers); ++#endif ++ vSemaphoreDelete(s_event_ctx.mutex); ++ puts("PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained"); ++} +diff --git a/tests/ws_subscriptions/test_init.c b/tests/ws_subscriptions/test_init.c +new file mode 100644 +index 0000000..42c0e46 +--- /dev/null ++++ b/tests/ws_subscriptions/test_init.c +@@ -0,0 +1,81 @@ ++#include "platform.h" ++#include ++#include "ts_ws_transport.h" ++#define MAX_WS_CLIENTS 8 ++#define TERMINAL_OUTPUT_BUF_SIZE 32768 ++#define TS_EVENT_BASE_POWER "power" ++#define TS_EVENT_ANY_ID -1 ++#define HTTP_GET 0 ++static struct {int active;} s_clients[MAX_WS_CLIENTS]; ++static httpd_handle_t s_server; ++static bool s_ws_stopping; ++static int s_terminal_client_fd; ++static SemaphoreHandle_t s_terminal_mutex,s_output_mutex; ++static char*s_terminal_output_buf; ++static size_t s_terminal_output_len; ++static ts_event_handler_handle_t s_power_event_handle; ++static int fail_stage,mutex_calls; ++static httpd_handle_t ts_http_server_get_handle(void){return fail_stage==1?NULL:(void*)11;} ++static void peer_closed(ts_ws_peer_t peer){(void)peer;} ++esp_err_t ts_ws_transport_start(httpd_handle_t server,ts_ws_closed_t fn){(void)server;(void)fn;return fail_stage==2?ESP_ERR_NO_MEM:ESP_OK;} ++static int ts_ws_subscriptions_init(void){return fail_stage==3?ESP_ERR_NO_MEM:ESP_OK;} ++static esp_err_t ts_webui_ws_stop(httpd_handle_t server); ++static int manager_stop_result,barrier_result,tx_stop_result,tx_stop_calls; ++static bool owner_context,s_exec_running,s_ssh_poll_alive,cleanup_finishes; ++static atomic_uint s_exec_creators; ++bool ts_ws_transport_in_context(void){return owner_context;} ++static esp_err_t ts_ws_subscriptions_deinit(void){return manager_stop_result;} ++esp_err_t ts_ws_transport_quiesce(httpd_handle_t server,uint32_t timeout){(void)server;(void)timeout;return barrier_result;} ++esp_err_t ts_ws_transport_stop(httpd_handle_t server,uint32_t timeout){(void)server;(void)timeout;tx_stop_calls++;return tx_stop_result;} ++static void ssh_cleanup(void){if(cleanup_finishes)s_ssh_poll_alive=false;} ++static void ts_webui_ws_stopped(httpd_handle_t server){(void)server;} ++static void ts_http_server_set_stop_hooks(esp_err_t(*a)(httpd_handle_t),void(*b)(httpd_handle_t)){(void)a;(void)b;} ++static SemaphoreHandle_t create_mutex(void){mutex_calls++;if(fail_stage==3+mutex_calls)return NULL;return xSemaphoreCreateMutex();} ++static void*buffer_alloc(size_t n){if(fail_stage==6)return NULL;return malloc(n);} ++static void*heap_alloc(size_t n,unsigned caps){(void)caps;return buffer_alloc(n);} ++static int ws_handler(httpd_req_t*r){(void)r;return 0;} ++static void power_policy_event_handler(const ts_event_t*e,void*u){(void)e;(void)u;} ++typedef struct {const char*uri;int method;int(*handler)(httpd_req_t*);void*user_ctx;bool is_websocket,handle_ws_control_frames;} httpd_uri_t; ++static int httpd_register_uri_handler(httpd_handle_t h,const httpd_uri_t*u){(void)h;(void)u;return fail_stage==7?ESP_FAIL:0;} ++static int register_event(const char*b,int id,void(*fn)(const ts_event_t*,void*),void*u,void**out){(void)b;(void)id;(void)fn;(void)u;if(fail_stage==8)return ESP_ERR_NO_MEM;*out=(void*)1;return 0;} ++#define xSemaphoreCreateMutex create_mutex ++#define malloc buffer_alloc ++#define heap_caps_malloc heap_alloc ++#define ts_event_register register_event ++#include "ws_init.inc" ++#undef xSemaphoreCreateMutex ++#undef malloc ++#undef heap_caps_malloc ++#undef ts_event_register ++#include "ws_stop.inc" ++ ++typedef struct {int unused;} ts_webui_ssh_options_t; ++esp_err_t ts_webui_ssh_exec_start(const char*,uint16_t,const char*,const char*,const char*,const char*,uint32_t*); ++static int creator_calls; ++static esp_err_t ts_webui_ssh_exec_start_impl(const char*h,uint16_t p,const char*u,const char*k,const char*w,const char*c,uint32_t*i){ ++ (void)h;(void)p;(void)u;(void)k;(void)w;(void)c;(void)i;creator_calls++; ++ assert(ts_webui_ssh_exec_start("fixture",22,"u",NULL,NULL,"fixture",NULL)==ESP_ERR_INVALID_STATE); ++ return ESP_OK; ++} ++static esp_err_t ts_webui_ssh_exec_start_ex_impl(const char*h,uint16_t p,const char*u,const char*k,const char*w,const char*c,const ts_webui_ssh_options_t*o,uint32_t*i){(void)o;return ts_webui_ssh_exec_start_impl(h,p,u,k,w,c,i);} ++#include "ws_creators.inc" ++static void reset(void){ ++ if(s_terminal_mutex)vSemaphoreDelete(s_terminal_mutex);if(s_output_mutex)vSemaphoreDelete(s_output_mutex);free(s_terminal_output_buf); ++ s_terminal_mutex=s_output_mutex=NULL;s_terminal_output_buf=NULL;s_server=NULL;s_power_event_handle=NULL;mutex_calls=0;s_ws_stopping=false; ++} ++int main(void){ ++ for(fail_stage=1;fail_stage<=8;fail_stage++){assert(ts_webui_ws_init()!=ESP_OK);reset();} ++ fail_stage=0;assert(ts_webui_ws_init()==0);assert(ts_webui_ws_init()==0);s_ws_stopping=true;assert(ts_webui_ws_init()==ESP_ERR_INVALID_STATE);reset(); ++ manager_stop_result=ESP_ERR_TIMEOUT;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(!tx_stop_calls); ++ manager_stop_result=0;barrier_result=ESP_ERR_TIMEOUT;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(!tx_stop_calls);barrier_result=0; ++ s_exec_creators=1;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);s_exec_creators=0; ++ s_exec_running=true;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);s_exec_running=false; ++ s_ssh_poll_alive=true;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);assert(!tx_stop_calls); ++ cleanup_finishes=true;tx_stop_result=ESP_ERR_TIMEOUT;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT);tx_stop_result=0;assert(ts_webui_ws_stop((void*)11)==0); ++ owner_context=true;assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE); ++ puts("PASS actual WebSocket stop: manager/barrier failures propagate, active SSH creation/execution retained, poller timeout retained, transport drain retry and HTTPD self-wait rejected"); ++ s_ws_stopping=false;assert(ts_webui_ssh_exec_start("fixture",22,"u",NULL,NULL,"fixture",NULL)==0);assert(creator_calls==1&&!s_exec_creators); ++ s_ws_stopping=true;assert(ts_webui_ssh_exec_start("fixture",22,"u",NULL,NULL,"fixture",NULL)==ESP_ERR_INVALID_STATE);assert(creator_calls==1&&!s_exec_creators); ++ puts("PASS actual SSH creation wrappers: concurrent builder rejected and stop admission closes without invoking the remote-operation implementation"); ++ puts("PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards"); ++} +diff --git a/tests/ws_subscriptions/test_lifecycle.c b/tests/ws_subscriptions/test_lifecycle.c +new file mode 100644 +index 0000000..f30a8eb +--- /dev/null ++++ b/tests/ws_subscriptions/test_lifecycle.c +@@ -0,0 +1,35 @@ ++#include "platform.h" ++#include ++static httpd_handle_t s_server=(void*)11; ++static bool s_initialized=true; ++static atomic_bool s_stopping; ++static atomic_flag s_stop_busy=ATOMIC_FLAG_INIT; ++static _Atomic(TaskHandle_t) s_http_task; ++static int s_route_count=4; ++static struct {void *owned_copy;} s_registered_routes[64]; ++static int hook_result,stop_result,stop_calls,after_calls; ++static esp_err_t before(httpd_handle_t h){assert(h==(void*)11);return hook_result;} ++static void after(httpd_handle_t h){assert(h==(void*)11);after_calls++;} ++static esp_err_t(*s_before_stop)(httpd_handle_t)=before; ++static void(*s_after_stop)(httpd_handle_t)=after; ++TaskHandle_t xTaskGetCurrentTaskHandle(void){return (void*)1;} ++static int httpd_stop(httpd_handle_t h){assert(h==(void*)11);stop_calls++;return stop_result;} ++#include "http_stop.inc" ++static httpd_handle_t ts_http_server_get_handle(void){return s_server;} ++static bool ts_http_server_is_stopping(void){return s_stopping;} ++#define s_initialized webui_initialized ++static bool s_initialized=true; ++static bool s_running=true; ++esp_err_t ts_webui_stop(void); ++#include "webui_stop.inc" ++#undef s_initialized ++int main(void){ ++ s_registered_routes[0].owned_copy=malloc(16); ++ hook_result=ESP_ERR_TIMEOUT;assert(ts_webui_stop()==ESP_ERR_TIMEOUT);assert(stop_calls==0&&s_server&&s_running&&s_registered_routes[0].owned_copy);assert(!ts_webui_is_running()); ++ assert(ts_webui_deinit()==ESP_ERR_TIMEOUT);assert(s_initialized&&webui_initialized); ++ hook_result=0;stop_result=ESP_FAIL;assert(ts_webui_stop()==ESP_FAIL);assert(s_server&&s_stopping&&after_calls==0); ++ stop_result=0;s_http_task=(void*)1;assert(ts_webui_stop()==ESP_ERR_INVALID_STATE);s_http_task=NULL; ++ assert(ts_webui_stop()==0);assert(!s_server&&!s_stopping&&!s_running&&after_calls==1&&!s_registered_routes[0].owned_copy); ++ assert(ts_webui_deinit()==0);assert(!s_initialized&&!webui_initialized);assert(ts_webui_stop()==0); ++ puts("PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry"); ++} +diff --git a/tests/ws_subscriptions/test_manager.c b/tests/ws_subscriptions/test_manager.c +new file mode 100644 +index 0000000..5493a20 +--- /dev/null ++++ b/tests/ws_subscriptions/test_manager.c +@@ -0,0 +1,207 @@ ++#define TEST_ALLOC ++#define TEST_FAIL_EVENTS ++#include "platform.h" ++static void *tracked_malloc(size_t n); ++static void tracked_free(void *p); ++#define malloc tracked_malloc ++#define free tracked_free ++static void capacity_done(uint64_t r,uint64_t d,esp_err_t e){(void)r;(void)d;(void)e;} ++static void test_point(const char *name); ++#define TS_WS_TEST_POINT(name) test_point(name) ++#define shutdown test_shutdown ++#define s_lock transport_lock ++#define s_server transport_server ++#define s_sequence transport_sequence ++#include "ts_ws_transport.c" ++#undef shutdown ++#undef s_lock ++#undef s_server ++#undef s_sequence ++#include "ts_ws_subscriptions.c" ++#undef malloc ++#undef free ++static unsigned allocations, live_allocations; ++static int fail_allocation; ++static void *tracked_malloc(size_t n) { ++ allocations++; if(fail_allocation>0 && allocations==(unsigned)fail_allocation)return NULL; ++ void*p=malloc(n);if(p)live_allocations++;return p; ++} ++static void tracked_free(void*p) {if(p){assert(live_allocations);live_allocations--;free(p);}} ++int test_result_frees, test_event_fail_at, test_event_registers; ++int64_t test_now=10000000; ++static TaskHandle_t current=(void*)1; ++static void(*worker_fn)(void*); ++static void(*delay_hook)(void); ++static void(*api_hook)(void); ++static bool queue_fail, immediate, send_fail, task_fail, api_business_error; ++static unsigned shutdowns; ++int test_shutdown(int fd,int how){(void)how;assert(fd>0);shutdowns++;return 0;} ++static void(*wait_hook)(void); ++static const char *barrier_name; ++static void(*barrier_action)(void); ++static void test_point(const char *name) {if(barrier_action && !strcmp(name,barrier_name)){void(*fn)(void)=barrier_action;barrier_action=NULL;fn();}} ++static unsigned reads[7], frames[32], notifications, queued; ++static char payloads[64][TS_WS_FRAME_BYTES]; ++static struct {void(*fn)(void*);void*arg;} queue[64]; ++TaskHandle_t xTaskGetCurrentTaskHandle(void) {return current;} ++int xTaskCreate(void(*fn)(void*),const char*n,unsigned stack,void*a,unsigned p,TaskHandle_t*out) {(void)n;(void)stack;(void)a;(void)p;if(task_fail)return 0;worker_fn=fn;*out=(void*)2;return pdPASS;} ++void xTaskNotifyGive(TaskHandle_t t) {assert(t==(void*)2);notifications++;} ++unsigned ulTaskNotifyTake(int clear,TickType_t ticks) {(void)clear;(void)ticks;assert(wait_hook);wait_hook();unsigned n=notifications;notifications=0;return n;} ++void vTaskDelete(TaskHandle_t t) {(void)t;} ++void vTaskDelay(TickType_t t) {test_now+=(int64_t)t*1000;if(delay_hook)delay_hook();} ++int httpd_ws_get_fd_info(httpd_handle_t h,int fd) {(void)h;(void)fd;return HTTPD_WS_CLIENT_WEBSOCKET;} ++int httpd_ws_send_frame_async(httpd_handle_t h,int fd,httpd_ws_frame_t*f) {(void)h;assert(fd>=0&&fd<32);frames[fd]++;memcpy(payloads[fd],f->payload,f->len);payloads[fd][f->len]=0;return send_fail?ESP_FAIL:0;} ++int httpd_queue_work(httpd_handle_t h,void(*fn)(void*),void*a) {(void)h;if(queue_fail)return ESP_FAIL;if(immediate) {TaskHandle_t saved=current;current=(void*)3;fn(a);current=saved;}else{assert(queued<64);queue[queued++]=(typeof(queue[0])){fn,a};}return 0;} ++int ts_api_call(const char*method,const cJSON*p,ts_api_result_t*r) {(void)p;for(int i=0;i<7;i++)if(!strcmp(metrics[i],method))reads[i]++;if(api_hook)api_hook();r->data=cJSON_CreateObject();r->message=malloc(8);r->code=api_business_error?1:0;return 0;} ++static void pump(void) { ++ while(queued || ts_ws_transport_needs_flush()){ ++ current=(void*)1;ts_ws_transport_flush(); ++ if(!queued)break; ++ assert(queued<=2); /* at most one TX control item plus a lifecycle barrier */ ++ current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(queue[0]));q.fn(q.arg); ++ } ++ current=(void*)1; ++} ++static void worker_exit(void) {if(s_worker){current=(void*)2;worker_fn(NULL);current=(void*)1;}} ++static void closed(ts_ws_peer_t peer) {ts_ws_client_disconnected(peer);} ++static httpd_req_t reqs[32]; ++static ts_ws_peer_t open_peer(int fd) {current=(void*)3;reqs[fd]=(httpd_req_t){.handle=(void*)11,.fd=fd};ts_ws_peer_t p;assert(ts_ws_peer_open(&reqs[fd],&p)==0);current=(void*)1;return p;} ++static void close_peer(int fd) {current=(void*)3;reqs[fd].free_ctx(reqs[fd].sess_ctx);reqs[fd].sess_ctx=NULL;current=(void*)1;} ++static void start(void) {assert(ts_ws_transport_start((void*)11,closed)==0);assert(ts_ws_subscriptions_init()==0);} ++static void stop(void) {delay_hook=worker_exit;assert(ts_ws_subscriptions_deinit()==0);delay_hook=NULL;pump();assert(ts_ws_transport_stop((void*)11,5)==0);for(int i=0;i<32;i++)if(reqs[i].sess_ctx)close_peer(i);ts_ws_transport_stopped((void*)11);assert(!s_outstanding);for(int i=0;i=0)cJSON_AddNumberToObject(j,"interval",interval);assert(ts_ws_subscribe(p,t,j)==0);cJSON_Delete(j);} ++static unsigned total_reads(void) {unsigned n=0;for(int i=0;i<7;i++)n+=reads[i];return n;} ++static ts_ws_peer_t cancel_peer; ++static void stop_during_api(void) {api_hook=NULL;assert(ts_ws_subscriptions_deinit()==ESP_ERR_TIMEOUT);assert(s_state==STOPPING);assert(ts_ws_subscriptions_init()==ESP_ERR_INVALID_STATE);} ++static void wake_at_wait(void) {wait_hook=NULL;subscribe(cancel_peer,"system.cpu",1000);assert(notifications);s_state=STOPPING;} ++static void resub_at_barrier(void) {ts_ws_unsubscribe(cancel_peer,"system.cpu");subscribe(cancel_peer,"system.cpu",10000);} ++static void reuse_at_barrier(void) {close_peer(1);cancel_peer=open_peer(1);subscribe(cancel_peer,"system.cpu",10000);} ++static int cross_action; ++static void cross_mutation(void) { ++ api_hook=NULL; ++ if(cross_action==0)ts_ws_unsubscribe(cancel_peer,"system.cpu"); ++ if(cross_action==1)resub_at_barrier(); ++ if(cross_action==2)close_peer(1); ++ if(cross_action==3)reuse_at_barrier(); ++ if(cross_action==4){TaskHandle_t saved=current;current=(void*)1;assert(ts_ws_subscriptions_deinit()==ESP_ERR_TIMEOUT);assert(ts_ws_subscriptions_init()==ESP_ERR_INVALID_STATE);current=saved;} ++} ++static void cancel_during_api(void) {api_hook=NULL;ts_ws_unsubscribe(cancel_peer,"system.dashboard");} ++int main(void) { ++ cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); ++ start();run_batch();assert(total_reads()==0);assert(next_wait()==portMAX_DELAY); ++ ts_ws_peer_t a=open_peer(1),b=open_peer(2);open_peer(3); ++ subscribe(a,"system.dashboard",1000);subscribe(b,"system.dashboard",10000); ++ run_batch();assert(total_reads()==0);test_now+=1000000;run_batch();assert(total_reads()==7);assert(queued==1);pump();assert(frames[1]==1&&frames[2]==0&&frames[3]==0); ++ unsigned n=total_reads();run_batch();assert(total_reads()==n); ++ subscribe(a,"system.dashboard",1000);run_batch();assert(total_reads()==n); /* idempotent */ ++ ts_ws_unsubscribe(a,"system.dashboard");test_now+=1000000;run_batch();assert(total_reads()==n); ++ ts_ws_unsubscribe(b,"system.dashboard");test_now+=10000000;run_batch();assert(total_reads()==n);assert(next_wait()==portMAX_DELAY); ++ puts("PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout"); ++ subscribe(a,"system.dashboard",1000);subscribe(b,"system.cpu",1000);test_now+=1000000;unsigned cpu=reads[0];run_batch();assert(reads[0]==cpu+1);assert(queued==1 && s_outstanding==2); ++ ts_ws_unsubscribe(a,"system.dashboard");subscribe(a,"system.dashboard",10000);pump();assert(frames[1]==1&&frames[2]==1);assert(!s_subs[0].pending); ++ puts("PASS T09 T12 T16: shared batch, old revision cannot send or update new state"); ++ ts_ws_unsubscribe(a,"system.dashboard");ts_ws_unsubscribe(b,"system.cpu"); ++ subscribe(a,"system.info",5000);test_now+=5000000;run_batch();assert(queued==1);close_peer(1);a=open_peer(1);pump();assert(frames[1]==1); ++ puts("PASS T11 T14: standalone info, queued delivery cannot cross fd reuse"); ++ subscribe(a,"system.dashboard",1000);cancel_peer=a;api_hook=cancel_during_api;test_now+=1000000;n=total_reads();run_batch();assert(total_reads()==n+1);assert(queued==0); ++ puts("PASS T13: cancellation during API skips remaining metrics"); ++ subscribe(a,"system.cpu",1000);test_now+=1000000;queue_fail=true;run_batch();assert(!s_outstanding);n=total_reads();run_batch();assert(total_reads()==n);queue_fail=false; ++ test_now+=1000000;immediate=true;run_batch();assert(!s_outstanding);immediate=false;assert(frames[1]==2); ++ puts("PASS T17 T19 T20: queue failure backoff, completion-before-return ownership"); ++ ts_ws_unsubscribe(a,"system.cpu");subscribe(a,"config.pack.validated",0); ++ cJSON*j=cJSON_Parse("{\"path\":\"first\"}");ts_ws_broadcast_to_topic("config.pack.validated",j);cJSON_SetValuestring(cJSON_GetObjectItem(j,"path"),"second");ts_ws_broadcast_to_topic("config.pack.validated",j);cJSON_Delete(j); ++ run_batch();assert(queued==1);pump();assert(strstr(payloads[1],"first"));run_batch();pump();assert(strstr(payloads[1],"second")); ++ puts("PASS T23: ordered operation events own borrowed data"); ++ const char*bad[]={"0","-1","1.5","\"1000\"","4294967296"};for(unsigned i=0;i<5;i++){j=cJSON_CreateObject();cJSON_AddItemToObject(j,"interval",cJSON_Parse(bad[i]));assert(ts_ws_subscribe(a,"system.cpu",j)==ESP_ERR_INVALID_ARG);cJSON_Delete(j);} ++ assert(wait_ticks(1)==1);assert(wait_ticks(INT64_MAX)>0);assert(wait_ticks(INT64_MAX)100);stop();assert(live_allocations==0); ++ puts("PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored"); ++ start();a=open_peer(1);b=open_peer(2);open_peer(3); ++ subscribe(a,"device.status",2000);const char raw[]={ '{','"','x','"',':','1','}' }; ++ ts_event_t ev={.data=(void*)raw,.data_size=sizeof(raw)};event_handler(&ev,(void*)8);event_handler(&ev,(void*)8); ++ run_batch();pump();before=frames[1];run_batch();assert(!queued);test_now+=2000000;run_batch();pump();assert(frames[1]==before+1); ++ httpd_ws_frame_t global={.payload=(uint8_t*)"{\"alarm\":true}",.len=14};unsigned f1=frames[1],f2=frames[2],f3=frames[3];assert(ts_ws_transport_broadcast(&global)==0);pump();assert(frames[1]==f1+1&&frames[2]==f2+1&&frames[3]==f3+1); ++ puts("PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set"); ++ ts_ws_unsubscribe(a,"device.status");subscribe(a,"config.pack.validated",0); ++ j=cJSON_CreateObject();uint64_t dropped=s_stats.event_dropped;for(int i=0;i=1000); ++ ts_ws_message_t *alarm=ts_ws_message_text("{}",2);assert(alarm);assert(ts_ws_transport_submit(b,alarm,0,0,NULL,NULL)==0);ts_ws_message_release(alarm);pump(); ++ for(int i=0;istats.success); ++ stop();assert(!live_allocations); ++ puts("PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters"); ++ for(int point=0;point<2;point++)for(int action=0;action<2;action++) { ++ start();cancel_peer=open_peer(1);subscribe(cancel_peer,"system.cpu",1000);test_now+=1000000; ++ n=total_reads();before=frames[1];barrier_name=point?"sent":"snapshot";barrier_action=action?reuse_at_barrier:resub_at_barrier; ++ run_batch();pump();assert(total_reads()==n+(point?1:0));assert(frames[1]==before+(point?1:0)); ++ subscription_t *current_sub=NULL;for(int i=0;iinterval==10000 && !current_sub->pending && current_sub->last_success==0); ++ stop();assert(!live_allocations); ++ } ++ puts("PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse"); ++ assert(after_ms(INT64_MAX-100,UINT32_MAX)==INT64_MAX); ++ start();a=open_peer(1);queue_fail=true;assert(ts_ws_transport_quiesce(a.server,1)==ESP_FAIL);queue_fail=false;assert(!transport_server.outstanding); ++ assert(ts_ws_transport_quiesce(a.server,1)==ESP_ERR_TIMEOUT);assert(queued==1&&transport_server.outstanding==1);assert(ts_ws_transport_quiesce(a.server,1)==ESP_ERR_TIMEOUT);assert(queued==1);pump();assert(ts_ws_transport_quiesce(a.server,1)==0);stop(); ++ start();a=open_peer(1);immediate=true;assert(ts_ws_transport_quiesce(a.server,1)==0);immediate=false;assert(!transport_server.outstanding);stop();assert(!live_allocations); ++ puts("PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return"); ++ start();a=open_peer(1);subscribe(a,"system.dashboard",1000);api_business_error=true;test_now+=1000000;run_batch();assert(!queued&&!s_outstanding&&live_allocations==1);api_business_error=false; ++ test_now+=1000000;run_batch();send_fail=true;pump();send_fail=false;assert(shutdowns==1);assert(!ts_ws_peer_get(a.server,a.fd,&b));close_peer(1);stop();assert(!live_allocations); ++ puts("PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand"); ++ for(int point=0;point<4;point++)for(cross_action=0;cross_action<5;cross_action++) { ++ start();cancel_peer=open_peer(1);subscribe(cancel_peer,"system.cpu",1000);test_now+=1000000; ++ before=frames[1];n=total_reads(); ++ if(point==0||point==3){barrier_name=point==0?"snapshot":"sent";barrier_action=cross_mutation;} ++ if(point==1)api_hook=cross_mutation; ++ run_batch();if(point==2)cross_mutation();pump(); ++ assert(frames[1]==before+(point==3?1:0));assert(total_reads()==n+(point==0?0:1)); ++ stop();assert(!live_allocations); ++ } ++ puts("PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain"); ++ ++ j=cJSON_CreateObject();cJSON *services=cJSON_AddObjectToObject(j,"services"),*array=cJSON_AddArrayToObject(services,"services"); ++ char service_name[32];memset(service_name,1,31);service_name[31]=0; ++ for(int i=0;i<32;i++){cJSON *item=cJSON_CreateObject();cJSON_AddStringToObject(item,"name",service_name);cJSON_AddStringToObject(item,"state","STARTING");cJSON_AddStringToObject(item,"phase","SECURITY");cJSON_AddBoolToObject(item,"healthy",true);cJSON_AddNumberToObject(item,"start_time_ms",UINT32_MAX);cJSON_AddNumberToObject(item,"start_duration_ms",UINT32_MAX);cJSON_AddItemToArray(array,item);} ++ ts_ws_message_t *max_services=ts_ws_message_json("system.dashboard",j,INT64_MAX/1000000);assert(max_services);printf("PASS T18 configured 32-service escaped-name fixture: %zu bytes within %u-byte frame budget\n",max_services->len,TS_WS_FRAME_BYTES);ts_ws_message_release(max_services);cJSON_Delete(j);assert(!live_allocations); ++ ++ ++ ++ ++ ++ return 0; ++} diff --git a/docs/repair/ws-subscriptions/evidence/allocation-finding.txt b/docs/repair/ws-subscriptions/evidence/allocation-finding.txt new file mode 100644 index 0000000..a436545 --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/allocation-finding.txt @@ -0,0 +1,3 @@ +Allocation sweep initially failed at allocation 10: live=2 versus session-only baseline=1. +SDK cJSON_AddItemReferenceToObject creates a reference then returns false when key allocation fails without reclaiming that reference. +Replaced with explicit short-lived borrowed reference and constant-key insertion, with ownership cleanup on every failure. diff --git a/docs/repair/ws-subscriptions/evidence/baseline-red.txt b/docs/repair/ws-subscriptions/evidence/baseline-red.txt new file mode 100644 index 0000000..27c4d13 --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/baseline-red.txt @@ -0,0 +1,14 @@ +T02 no subscribers: API reads=7 (expected 0) +Expected business assertion failure: T02 +T05 before next deadline: API reads=7 (expected 0) +Expected business assertion failure: T05 +T06/T07 2 targets, 3 connected: global broadcast calls=2 => 6 frames (expected 2 targeted frames) +Expected business assertion failure: T07 +In file included from tests/ws_subscriptions/test_event.c:4: +/tmp/ts-ws-baseline.WTMhh8/ts_event.c:721:23: warning: result of comparison against a string literal is unspecified (use an explicit string comparison function instead) [-Wstring-compare] + 721 | if (handler->base != TS_EVENT_ANY_BASE && handler->base != NULL) { + | ^ ~~~~~~~~~~~~~~~~~ +1 warning generated. +./tests/ws_subscriptions/run_baseline.sh: line 24: 98428 Abort trap: 6 "$build/event" > "$build/event.log" 2>&1 +==98428==ERROR: AddressSanitizer: heap-use-after-free on address 0x6040000009b0 at pc 0x00010430885c bp 0x00016bafa010 sp 0x00016bafa008 +Expected T32 baseline failure: actual dispatch accesses self-unregistered freed node diff --git a/docs/repair/ws-subscriptions/evidence/baseline.json b/docs/repair/ws-subscriptions/evidence/baseline.json new file mode 100644 index 0000000..be1a0e4 --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/baseline.json @@ -0,0 +1,11 @@ +{ + "head": "35238b4645ae5e9e0e99555d4fb64080d945565c", + "branch": "fix/v0.5.2-reliability-and-prompts", + "status": "?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt\n?? output/\n?? tmp/", + "remotes": "fork\thttps://github.com/massif-01/TianshanOS.git (fetch)\nfork\thttps://github.com/massif-01/TianshanOS.git (push)\norigin\thttps://github.com/RMinte/TianshanOS (fetch)\norigin\thttps://github.com/RMinte/TianshanOS (push)", + "sha256": { + "components/ts_webui/src/ts_ws_subscriptions.c": "d082852a6e0e1811a3b791f97dde48f0d452d91b63168bc3b5ac275eb7f2bdb9", + "components/ts_webui/src/ts_webui_ws.c": "48f3d045fb4522d95d60c6c32633220d0761209d772b91989085801bb2c61c64", + "components/ts_core/ts_event/src/ts_event.c": "64e988c10aa267fdb7d7fe9d2f2532510a09c48a0d877560c145c568d5c08944" + } +} diff --git a/docs/repair/ws-subscriptions/evidence/browser.txt b/docs/repair/ws-subscriptions/evidence/browser.txt new file mode 100644 index 0000000..99acf8b --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/browser.txt @@ -0,0 +1,46 @@ +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (1322.276542ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (253.712708ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (293.583417ms) +✔ en-US: initial language failure blocks controls and retry recovers (359.235625ms) +✔ delayed language package and rapid switches keep the latest requested language (278.384042ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (343.014833ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (341.160416ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (350.750167ms) +✔ initial delayed language keeps controls inert until the real package arrives (229.216833ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (362.679833ms) +✔ terminal can initialize after failed resource load using newly served resources (394.451292ms) +✔ review2: successful retry retains old failure zh-CN (1255.2385ms) +✔ review2: prior completion closes new package confirmation zh-CN (206.934916ms) +✔ review2: uploaded file missing after dialog close zh-CN (193.256833ms) +✔ review2: successful retry retains old failure en-US (235.599708ms) +✔ review2: prior completion closes new package confirmation en-US (260.557208ms) +✔ review2: uploaded file missing after dialog close en-US (281.35075ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (195.632583ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (166.452459ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (168.332833ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (174.766958ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (203.446625ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (165.160917ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (260.099834ms) +✔ R3: late validation cannot revive an old apply entry en-US (241.685167ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (224.730584ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (243.901292ms) +✔ R6: fixed upload destination and separate refresh failure en-US (226.192291ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (234.449292ms) +✔ R2: authenticated startup initializes once (271.784208ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (243.631583ms) +✔ R4/R5: newest result wins over late success and late failure (221.469541ms) +✔ R3: overlapping writes to one path cannot claim current verified content (227.251833ms) +✔ R2: disposed page only removes its dashboard callback (267.292417ms) +✔ R2: stale finally cannot unlock the new page read (214.759ms) +✔ R1: delayed sign-out does not clear a newer sign-in (218.671084ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (277.515ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (359.278541ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 7607.990125 diff --git a/docs/repair/ws-subscriptions/evidence/build.txt b/docs/repair/ws-subscriptions/evidence/build.txt new file mode 100644 index 0000000..6c96f3c --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/build.txt @@ -0,0 +1,10 @@ +SDK: ESP-IDF v5.5.2 +Target: ESP32-S3 +Command: idf.py -B /tmp/tianshan-ws-build/build -D SDKCONFIG=/tmp/tianshan-ws-build/sdkconfig build +Exit code: 0 +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +TianShanOS.bin binary size 0x211be0 bytes. Smallest app partition is 0x300000 bytes. 0xee420 bytes (31%) free. +Project build complete. To flash, run: +Firmware: /tmp/tianshan-ws-build/build/TianShanOS.bin +SHA256: 8c8da47bb61b734054b99ea4680df562e5b2be379bc57c006dc9064d5f4b0e7b +Compile only; SDK-printed flashing instructions NOT executed. Repository build/*.bin and sdkconfig unchanged. diff --git a/docs/repair/ws-subscriptions/evidence/certificate.txt b/docs/repair/ws-subscriptions/evidence/certificate.txt new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/certificate.txt @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ws-subscriptions/evidence/diff-check.txt b/docs/repair/ws-subscriptions/evidence/diff-check.txt new file mode 100644 index 0000000..86b384f --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/diff-check.txt @@ -0,0 +1 @@ +git diff --check: 0 diff --git a/docs/repair/ws-subscriptions/evidence/final-manifest.json b/docs/repair/ws-subscriptions/evidence/final-manifest.json new file mode 100644 index 0000000..438fd7b --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/final-manifest.json @@ -0,0 +1,39 @@ +{ + "head": "35238b4645ae5e9e0e99555d4fb64080d945565c", + "files": { + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/src/ts_http_server.c": "b3a09f6da5f61d77c5d302d33880a9f94372119aece3eccaa468e5822964d97b", + "components/ts_webui/CMakeLists.txt": "9a52c046ca47d6e19fa001796ed7469387566e4cfb176a85d55a5f1b96f2fcfa", + "components/ts_webui/include/ts_ws_subscriptions.h": "d10d6f29a5848f67ccc5f4658fce093c76725e4f418a188d0fdb68b8f3788b78", + "components/ts_webui/include/ts_ws_transport.h": "2a16916ffa8c36df453b1036326bea74c94640e41844225e3a97b4d694defe86", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_ws.c": "64b514731d3f9228ef5a10734e47fb2efbc9e3563965d823b66b61dec6b57900", + "components/ts_webui/src/ts_ws_subscriptions.c": "312e4876ab6acf25086a203292a2136658eb5a010d3c514b0b5d3a5b0da5f616", + "components/ts_webui/src/ts_ws_transport.c": "440b6ed0b421c2a7fcff282073e9168c419f0202e0d2f65aa72aa7c0f2f675ac", + "tests/prompts/ownership.browser.test.cjs": "1938411e7cc76ecc190b3469c58e58fd8aaa4a080ede60989190b4abd1147903", + "tests/ws_subscriptions/README.md": "b7f6adbc69d4a03e3d44b151b63fad9af433a4096842c8409ffb103039857260", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "81a5e44c179a1e8d76955bd445eef6a21b461fe7573916185e1f75f3e7b989f9", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_init.c": "e75d00b2c7ae6f1f76f97407eeb12037352448e80e377f854a08ddf15ca5c9b1", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/test_manager.c": "18d5e0cf07776eb1da1540763c80314d4fa6a0559253c5596a79e5bc87f41741" + } +} diff --git a/docs/repair/ws-subscriptions/evidence/host.txt b/docs/repair/ws-subscriptions/evidence/host.txt new file mode 100644 index 0000000..377bb50 --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/host.txt @@ -0,0 +1,25 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket stop: manager/barrier failures propagate, active SSH creation/execution retained, poller timeout retained, transport drain retry and HTTPD self-wait rejected +PASS actual SSH creation wrappers: concurrent builder rejected and stop admission closes without invoking the remote-operation implementation +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-subscriptions/evidence/prompts.txt b/docs/repair/ws-subscriptions/evidence/prompts.txt new file mode 100644 index 0000000..e4bb4bf --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/prompts.txt @@ -0,0 +1,46 @@ +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (18.518958ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.375833ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (8.139459ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.43475ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (6.253333ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.238459ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (6.433208ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.343667ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.664792ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.65675ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.699709ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.15825ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.680792ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (5.357583ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.440416ms) +✔ en-US: timeout covers response body; result stays unknown for POST (5.782375ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.413625ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (6.080292ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.897042ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.60625ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.955083ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (8.226791ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.655959ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.499625ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.992792ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.749417ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (5.533458ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (5.467916ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.757125ms) +✔ en-US: upload and download aggregates cover all success and all failure (4.941292ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (4.557041ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (5.097708ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (5.37975ms) +✔ zh-CN: unknown stop result never escalates to forced termination (6.302792ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.935ms) +✔ en-US: unknown stop result never escalates to forced termination (4.708959ms) +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.716958ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.099416ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 260.92625 diff --git a/docs/repair/ws-subscriptions/evidence/resources.txt b/docs/repair/ws-subscriptions/evidence/resources.txt new file mode 100644 index 0000000..f96b4ea --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/resources.txt @@ -0,0 +1,17 @@ +00000000 00000160 B ws_tcb_size +/tmp/tianshan-ws-build/build/esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj: +00000000 00000008 d s_lock +00000000 0000000c b s_handlers +00000000 0000001f T ts_ws_subscriptions_wake +00000000 000000f0 T ts_ws_subscriptions_init +00000000 00000128 b s_stats +00000000 000001d3 T ts_ws_subscriptions_deinit +00000000 000002e9 T ts_ws_subscribe +00000000 00000460 b s_events +00000000 00000a00 b s_subs +00000000 00000008 d s_lock +00000000 00000020 b s_server +00000000 00000048 b s_tx_stats +00000000 00000080 b s_messages +00000000 00000100 b s_peers +00000000 00000c80 b s_deliveries diff --git a/docs/repair/ws-subscriptions/evidence/runtime.txt b/docs/repair/ws-subscriptions/evidence/runtime.txt new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/runtime.txt @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ws-subscriptions/evidence/tsan.txt b/docs/repair/ws-subscriptions/evidence/tsan.txt new file mode 100644 index 0000000..29d22c6 --- /dev/null +++ b/docs/repair/ws-subscriptions/evidence/tsan.txt @@ -0,0 +1 @@ +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained diff --git a/docs/repair/ws-subscriptions/pr-update-gate.md b/docs/repair/ws-subscriptions/pr-update-gate.md new file mode 100644 index 0000000..f78f648 --- /dev/null +++ b/docs/repair/ws-subscriptions/pr-update-gate.md @@ -0,0 +1,19 @@ +# PR #42 增量提交检查(2026-09-25) + +结论:可以推送。用户已授权将本轮新修改提交到 Fork 并更新原 PR;不合并、不打标签、不发布、不操作设备。 + +本轮提交基于 `35238b4645ae5e9e0e99555d4fb64080d945565c`,包含 WebSocket 按需采集/定向发送及 R1—R5 修复、相关事件/HTTP/服务/核心停止链、生产 C 与浏览器回归、冻结基线和修复证据,以及更新的 v0.5.2 中文发布说明。原 `output/`、`tmp/` 和 `docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt` 不进入本次提交并保留原状。 + +## 审查依据 + +- 查看最终 manager/transport 的资源所有权、连接身份、发送前校验、关键结果预留和公平调度,及事件注销、HTTP/WS/服务/核心停止的错误传播。 +- 确认普通发送仍有界;关键结果入队重试不会重放 SSH 命令;外部设备、完整事件生产者和网络送达不作无条件保证。 +- 再跑 `bash tests/ws_subscriptions/run_reviewer.sh` 与 `bash tests/ws_subscriptions/run_host.sh` 成功;日志保存在本目录 `pr-update-reviewer.txt`、`pr-update-host.txt`。 +- 再跑 `python3 tests/release/test_release.py` 成功;生产源码、当前测试及发布文档的暂存差异检查成功。完整暂存 `git diff --cached --check` 会报告两份历史 `.patch` 及两份冻结旧函数夹具原有的尾随空格;为保留补丁上下文和复现证据不改写这些文件,检查时明确排除这四个证据文件。版本与发布工作流没有修改。 +- 当前源码逐文件 SHA-256 与 reviewer-fixes/final-manifest.json 一致,隔离目录的构建二进制哈希也一致,因此复用该次 ESP-IDF 构建及既有运行时/证书/浏览器证据,不将旧 PR 的 CI 绿灯用于新提交。 + +## 边界 + +主机测试依赖实际生产 C、模拟 SDK/RTOS/设备响应和 pthread 屏障;浏览器使用模拟服务。没有真实 ESP32 双核并发、慢连接/RST/LRU、长期堆和栈水位验收。现有 `/ws` 独立认证/主题授权缺口仍未解决。详细资源取舍及实机清单见 reviewer-fixes/README.md。 + +修复记录中的“未提交、未推送”是此前交付时点的事实;本文件记录后续授权下的提交前审查,最终远端 SHA 和 CI 以 PR #42 为准。 diff --git a/docs/repair/ws-subscriptions/pr-update-host.txt b/docs/repair/ws-subscriptions/pr-update-host.txt new file mode 100644 index 0000000..377bb50 --- /dev/null +++ b/docs/repair/ws-subscriptions/pr-update-host.txt @@ -0,0 +1,25 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket stop: manager/barrier failures propagate, active SSH creation/execution retained, poller timeout retained, transport drain retry and HTTPD self-wait rejected +PASS actual SSH creation wrappers: concurrent builder rejected and stop admission closes without invoking the remote-operation implementation +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-subscriptions/pr-update-reviewer.txt b/docs/repair/ws-subscriptions/pr-update-reviewer.txt new file mode 100644 index 0000000..dc04122 --- /dev/null +++ b/docs/repair/ws-subscriptions/pr-update-reviewer.txt @@ -0,0 +1,17 @@ +PASS R1: busy stop retains real worker; final fanout drains with no new producer message +PASS R1 timeout: handler-barrier and transport-drain failures retain worker; accepted fanout progresses before retry +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid +PASS R2 exec: admitted result reservation survives ordinary saturation and preserves recipients at completion +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/README.md b/docs/repair/ws-subscriptions/reviewer-fixes/README.md new file mode 100644 index 0000000..f276747 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/README.md @@ -0,0 +1,73 @@ +# R1—R5 修复与验证记录(2026-09-25) + +结论:五项确认问题已完成本地修复及生产代码回归;按需采集、同批指标共享、单次序列化与定向发送方案保留。此结论不等同于实机验收,也不覆盖所有历史 SSH/事件总线代码。 + +## 基线与改动范围 + +本轮起点是 HEAD `35238b4645ae5e9e0e99555d4fb64080d945565c` **加上当时全部相关未提交修改**,不是回退到该提交。`baseline.json` 记录分支、HEAD、逐文件 SHA-256;`pre-fix-source.tar.gz` 保存相关生产源码和当时的主机测试。没有覆盖原来其他工作,没有 commit、push、PR、版本、发布流程或设备操作。 + +在修改前复跑第一、二轮反例;另提供 `bash tests/ws_subscriptions/run_reviewer_baseline.sh`:校验归档内哈希,在临时目录编译归档中的生产 C,重新确认五项缺陷。该脚本退出 0 表示反例成立,不是修复通过。`baseline-replay.txt` 是本轮冻结基线的重放记录。归档含旧测试辅助代码;SDK cJSON 使用本机 ESP-IDF v5.5.2,未把其副本封入归档。 + +本轮差异见 `reviewer-fixes.patch`,相对于上述未修复基线生成,避免混淆更早的 WebUI 修改。`final-manifest.json` 记录最终源文件和证据哈希。 + +## 逐项状态与行为证据 + +| 问题 | 本地处理状态 | 行为证据 | +|---|---|---| +| R1 停止失败后发送无人推进 | 已修复 | 实际 `ws_stop` 返回 busy 后,真实 worker 仍处理最后一条保留的 SSH exec 结果;不再有新生产者消息时,两连接仍收到结果。HTTPD 屏障超时、transport 排空超时也保留推进能力,重试可完成。实际 `ws_handler` 在停止中继续响应心跳,拒绝新命令但不主动断开结果连接。 | +| R2 失败启动误报成功、终态被挤掉 | 已修复 | 实际 Shell 连接处理器注入任务创建失败、创建后 Shell 已关闭,最后收到错误而非 connected;普通消息池占满不影响保留终态。旧 READY 在终态后失效;SDK 拒绝队列提交时,关键终态保留并在退避后继续发送。普通 Shell 输出提交失败会明确报错并结束该流,不伪装为完整输出。 | +| R3 日志资格与角色脱节、重新订阅恢复旧日志 | 已修复 | 实际角色切换同步日志资格;日志→终端、日志→SSH 的旧日志失效。取消后同连接重新订阅,旧排队日志仍因代次不符被丢弃,新日志可发送。日志回调注销 busy 时保留句柄,随后重新订阅可以恢复启用。 | +| R4 上层忽略停止失败 | 已修复 | 实际服务聚合停止在第一个失败处返回,保留服务表与低阶段依赖;错误消失后重试成功。真实事件回调保持在途时,核心收到真实排空超时,日志/配置未被释放。分阶段 deinit、初始化回滚失败及之后重试均保留正确状态;重复 stop 不重放 shutdown 事件。 | +| R5 主题饥饿、无发送预算仍采集 | 已修复 | 八主题、六个普通遥测消息槽的受控调度中,100 轮各主题均在模拟 SDK 发送边界观察到 75 帧;基线后两主题为 0。消息槽、描述符或总字节预算分别耗尽时均无 API 采集;容量释放后仍到期的主题可继续服务,无需先等待另一个完整 interval。 | + +测试用的是完整生产 manager/transport/event C,以及从当前文件提取的完整 WebUI/服务/核心函数体。没有另写一份业务逻辑副本。SDK 网络、RTOS 调度、设备 API、SSH 远端响应为模拟;事件排空使用真实 pthread 屏障。R1 组合测试运行真实 worker 的一个调度片段及 SDK 回调,没有用原 `pump()` 替生产代码补一次 flush 来证明其进展。 + +## 实际逻辑与文件 + +- `ts_ws_subscriptions.c/.h`:增加 DRAINING 阶段。暂停新订阅/周期采集与销毁 worker 分离;已有操作结果订阅保留到生产者收尾、结果队列排空。按轮转顺序选择主题,采集前取得实际消息、发送描述符及字节所有权;不足时不前移该订阅的服务期限。堆失败有退避。 +- `ts_ws_transport.c/.h`:增加有界 reservation,供遥测批次与已接受 SSH 任务使用。预留不等于已发送;实际提交后由 HTTPD 所有者检查连接身份。停止时拒绝新的提交,但继续发送已经接受的工作;关键终态遇 SDK 入队失败保持 FIFO 所有权,100 ms 退避重试,不重新执行 SSH 命令。日志消息附带订阅代次;容量/分配拒绝进入计数。 +- `ts_webui_ws.c`:停止顺序为关闭新业务 → 暂停遥测 → HTTPD 请求屏障 → 等待 SSH 创建/执行与轮询收尾 → 注销自己的事件/日志生产者 → 排空结果 → transport drain → manager deinit。任何失败保留后续依赖和 worker。新握手拒绝,已有连接可心跳/取消订阅,新命令返回协议错误。角色和日志资格统一更新。 +- 同文件的 Shell:任务创建成功且当前 Shell 活跃后才进入 READY;轮询任务在 STARTING 时不输出。状态使用单调会话代次,READY 不能在终态后重新生效;上一终态尚未完成发送时不接受替代会话。Shell 和 exec 在接受前分别拥有关键结果预留。终态编码失败/过大时发送明确错误或结果未知,不能冒充成功。对端已断开或实际 socket 发送失败仍可能无法送达,记录失败并按连接生命周期处理,不宣称端到端可靠送达。 +- `ts_http_server.c`:停止阶段在读取请求体、调用业务 handler 前拒绝新的非 GET 请求;GET 读请求保留。底层停止失败继续保留实例。 +- `ts_service.c`、`main/ts_core_init.c`:逐层传播停止、保存与销毁失败;按阶段保留初始化/停止状态,阻止未完成停止时误报重新启动成功。初始化回滚复用同一释放顺序;已完成阶段不重复释放;同一停止意图不重放 shutdown 事件。 +- `tests/ws_subscriptions/`:新增冻结基线重放、manager/transport/WebUI 组合、服务、核心及 HTTP 入口回归;旧主机测试的提取依赖、SDK 请求结构与发送观察 hook 随真实接口更新。 + +没有改变硬件保护、风扇/传感器底层采样、SSH 匹配规则或前端框架。原普通日志/广播仍为有界发送,并未被改为“无限可靠流”;关键结果有独立配额和可观测失败处理。 + +## 资源预算和取舍 + +默认 8 个连接时,普通部分保持 32 个主题描述符 + 8 个普通广播/流描述符、6 个遥测消息槽 + 2 个普通文本槽;额外保留 2 个关键结果消息槽和 16 个结果目标描述符。**所有消息共同受 1 MiB 总字节上限约束,未上调总上限。** + +Shell 接受前预留 4096 字节及一个目标;exec 接受前预留 512 KiB 最大兼容结果缓冲及最多 8 个目标。exec 完成时快照实际全局接收者,保留原广播接收集合语义。预留会占用可用堆与普通消息预算;资源不足时明确拒绝接受新任务,不等任务执行完才发现没有终态容量。此前已接受结果尚在发送时,也可能暂时不能接受下一任务。 + +目标编译器检查:worker 仍为一个,栈 8192 字节、优先级 2;`run_batch` 栈帧 3360 字节,`collect_batch` 176 字节,worker 自身 32 字节。它们**不是完整调用链峰值或实机水位**;API/cJSON/SDK 调用仍有额外栈开销。静态 transport 描述符表 4480 字节、消息控制表 160 字节,两份任务 reservation 各 136 字节。详见 `resources.txt`。 + +## 实际执行命令与证据 + +| 层级 | 命令 | 结果/证据 | +|---|---|---| +| 未修复基线反例 | `bash tests/ws_subscriptions/run_reviewer_baseline.sh` | 冻结源码哈希核对通过,五项缺陷再次确认;`baseline-replay.txt`。 | +| 本次生产 C 组合回归 | `bash tests/ws_subscriptions/run_reviewer.sh` | ASan/UBSan 下上述行为断言通过;`reviewer-tests.txt`。 | +| 既有 WS/事件/生命周期主机回归 | `bash tests/ws_subscriptions/run_host.sh` | 通过;`host.txt`。 | +| 既有运行时回归 | `bash tests/runtime/run_all.sh` | 通过;`runtime.txt`。 | +| 既有证书/HTTPS 回归 | `bash tests/certificate/run_host.sh` | 通过;`certificate.txt`。其中 REPRODUCED 为该套件自己的旧版反例。 | +| 前端静态/Node 逻辑 | `npm test --prefix tests/prompts` | 通过;`prompts.txt`。 | +| 本地 Chrome 浏览器 | `npm run test:browser --prefix tests/prompts` | 中英文既有回归通过;`browser.txt`。首次沙箱内 Chrome 启动失败,沙箱外使用临时配置重跑成功。WebSocket/设备响应模拟,不是 C 后端联机测试。 | +| 目标编译/链接/分区 | ESP-IDF v5.5.2:`idf.py -B /tmp/tianshan-ws-build/build -D SDKCONFIG=/tmp/tianshan-ws-build/sdkconfig build` | 本地 ESP32-S3 固件构建通过,结果与分区余量见 `build.txt`。未刷写。 | +| 静态差异 | `git diff --check` | 通过;`diff-check.txt`。 | + +构建前设置 `DEVELOPER_DIR=/Library/Developer/CommandLineTools`,Python 环境为 `/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin`,并加载 `/Users/massif/esp/v5.5.2/esp-idf/export.sh`。资源检查使用同一 `compile_commands.json` 的目标编译参数加 `-fstack-usage`,输出放在 `/tmp/ws-reviewer-stack`。 + +## 未执行和实机验收边界 + +没有设备连接、刷机、重启、真实 SSH、远端模型或电源操作。没有 commit/push/PR/发布操作。未运行 ESP32 双核调度压力、真实 TCP 慢接收/RST/LRU、长时间运行、实际最大业务数据、PSRAM 碎片及真实栈水位;本地浏览器未连接实际生产 C 服务器。 + +需要另行授权的实机验收: + +1. 多标签页快慢订阅、八主题同时到期;无需求/未到期时采集计数不增长,容量恢复后各主题有进展。 +2. SSH 运行期间停止 WebUI,观察 busy/timeout、心跳及最后输出/终态;失败后不产生新消息也能排空,随后重试完成停止,再启动成功。 +3. 任务创建/内存不足、启动后立即远端关闭、SDK 控制队列拥塞与连接断开;不出现迟到 connected,也不重放远端命令。 +4. 日志→终端/SSH、取消再订阅、断线重连与 fd 复用;旧日志不恢复资格,原全局告警接收行为保留。 +5. 服务/事件停止超时,确认依赖继续存活,资源只在排空后释放;观察堆回归、固定池峰值、发送耗时及 worker 最低栈水位。 + +已修复指上述本地证据覆盖的五项行为,不代表全部历史后台发送者、全局事件总线外部生产者并发销毁或全部设备故障模式已经通过验收。 diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/baseline-r1-r3.txt b/docs/repair/ws-subscriptions/reviewer-fixes/baseline-r1-r3.txt new file mode 100644 index 0000000..46fe71d --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/baseline-r1-r3.txt @@ -0,0 +1,3 @@ +CONFIRMED R1: stop returned busy; worker absent; accepted two-recipient message sent to only one; pending jobs=1 +CONFIRMED R2: three real ssh_send_status calls produce two frames; final frame={"type":"ssh_status","status":"connected","message":"SSH shell ready"} +CONFIRMED R3: actual terminal_start changes client role, but both queued and new log frames still reach this peer diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/baseline-r4-r5.txt b/docs/repair/ws-subscriptions/reviewer-fixes/baseline-r4-r5.txt new file mode 100644 index 0000000..8e2c2b3 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/baseline-r4-r5.txt @@ -0,0 +1,11 @@ +CONFIRMED R4: actual event drain timed out at 6000000 us, but actual core_deinit returned OK and deinitialized log/config while callback was still running +CONFIRMED R4 aggregate: failed WebUI stop was ignored; lower-phase dependency stopped; service_deinit released registry and returned OK despite repeated failure +system.dashboard: api=100 serialized=100 +system.info: api=100 serialized=100 +system.memory: api=100 serialized=100 +system.cpu: api=100 serialized=100 +network.status: api=100 serialized=100 +power.status: api=100 serialized=100 +fan.status: api=100 serialized=0 +service.list: api=100 serialized=0 +CONFIRMED R5: fan/status and service/list starve for 100 completed cycles, although their APIs are collected each time diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/baseline-replay.txt b/docs/repair/ws-subscriptions/reviewer-fixes/baseline-replay.txt new file mode 100644 index 0000000..9d2f5a6 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/baseline-replay.txt @@ -0,0 +1,14 @@ +CONFIRMED R1: stop returned busy; worker absent; accepted two-recipient message sent to only one; pending jobs=1 +CONFIRMED R2: three real ssh_send_status calls produce two frames; final frame={"type":"ssh_status","status":"connected","message":"SSH shell ready"} +CONFIRMED R3: actual terminal_start changes client role, but both queued and new log frames still reach this peer +system.dashboard: api=100 serialized=100 +system.info: api=100 serialized=100 +system.memory: api=100 serialized=100 +system.cpu: api=100 serialized=100 +network.status: api=100 serialized=100 +power.status: api=100 serialized=100 +fan.status: api=100 serialized=0 +service.list: api=100 serialized=0 +CONFIRMED R5: fan/status and service/list starve for 100 completed cycles, although their APIs are collected each time +CONFIRMED R4: actual event drain timed out at 6000000 us, but actual core_deinit returned OK and deinitialized log/config while callback was still running +CONFIRMED R4 aggregate: failed WebUI stop was ignored; lower-phase dependency stopped; service_deinit released registry and returned OK despite repeated failure diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/baseline.json b/docs/repair/ws-subscriptions/reviewer-fixes/baseline.json new file mode 100644 index 0000000..4d7fdb4 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/baseline.json @@ -0,0 +1,42 @@ +{ + "head": "35238b4645ae5e9e0e99555d4fb64080d945565c", + "branch": "fix/v0.5.2-reliability-and-prompts", + "sha256": { + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_core/ts_service/src/ts_service.c": "60654bcab3883b814d82a1e119c26d3a3aba1ea614edaae0927622f3733c9480", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/src/ts_http_server.c": "b3a09f6da5f61d77c5d302d33880a9f94372119aece3eccaa468e5822964d97b", + "components/ts_webui/CMakeLists.txt": "9a52c046ca47d6e19fa001796ed7469387566e4cfb176a85d55a5f1b96f2fcfa", + "components/ts_webui/include/ts_ws_subscriptions.h": "d10d6f29a5848f67ccc5f4658fce093c76725e4f418a188d0fdb68b8f3788b78", + "components/ts_webui/include/ts_ws_transport.h": "2a16916ffa8c36df453b1036326bea74c94640e41844225e3a97b4d694defe86", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_ws.c": "64b514731d3f9228ef5a10734e47fb2efbc9e3563965d823b66b61dec6b57900", + "components/ts_webui/src/ts_ws_subscriptions.c": "312e4876ab6acf25086a203292a2136658eb5a010d3c514b0b5d3a5b0da5f616", + "components/ts_webui/src/ts_ws_transport.c": "440b6ed0b421c2a7fcff282073e9168c419f0202e0d2f65aa72aa7c0f2f675ac", + "main/ts_core_init.c": "912a95a58cb59aebc8d463022fea24bf516cae877675cbf33819ac5b3b2ca068", + "tests/prompts/ownership.browser.test.cjs": "1938411e7cc76ecc190b3469c58e58fd8aaa4a080ede60989190b4abd1147903", + "tests/ws_subscriptions/README.md": "b7f6adbc69d4a03e3d44b151b63fad9af433a4096842c8409ffb103039857260", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "81a5e44c179a1e8d76955bd445eef6a21b461fe7573916185e1f75f3e7b989f9", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_init.c": "e75d00b2c7ae6f1f76f97407eeb12037352448e80e377f854a08ddf15ca5c9b1", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/test_manager.c": "18d5e0cf07776eb1da1540763c80314d4fa6a0559253c5596a79e5bc87f41741" + } +} \ No newline at end of file diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/browser.txt b/docs/repair/ws-subscriptions/reviewer-fixes/browser.txt new file mode 100644 index 0000000..71251ee --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/browser.txt @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (1191.476708ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (296.032167ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (341.341ms) +✔ en-US: initial language failure blocks controls and retry recovers (367.007708ms) +✔ delayed language package and rapid switches keep the latest requested language (304.905125ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (387.868625ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (317.535166ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (364.884583ms) +✔ initial delayed language keeps controls inert until the real package arrives (259.443875ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (411.715208ms) +✔ terminal can initialize after failed resource load using newly served resources (409.717125ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (1115.985834ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (204.44425ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (186.555625ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (270.177834ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (288.351167ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (273.655167ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (196.63325ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (193.383625ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (172.962584ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (205.011042ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (218.055583ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (195.711625ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (279.554208ms) +✔ R3: late validation cannot revive an old apply entry en-US (294.909334ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (261.60375ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (248.518166ms) +✔ R6: fixed upload destination and separate refresh failure en-US (256.573292ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (262.662833ms) +✔ R2: authenticated startup initializes once (299.005834ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (247.576833ms) +✔ R4/R5: newest result wins over late success and late failure (253.701ms) +✔ R3: overlapping writes to one path cannot claim current verified content (241.891958ms) +✔ R2: disposed page only removes its dashboard callback (285.388625ms) +✔ R2: stale finally cannot unlock the new page read (243.782083ms) +✔ R1: delayed sign-out does not clear a newer sign-in (222.310833ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (337.58075ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (365.708209ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 8000.525959 diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/build.txt b/docs/repair/ws-subscriptions/reviewer-fixes/build.txt new file mode 100644 index 0000000..9a56f41 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/build.txt @@ -0,0 +1,30 @@ +Executing action: all (aliases: build) +Running ninja in directory /private/tmp/tianshan-ws-build/build +Executing "ninja all"... +[1/10] Performing build step for 'bootloader' +[1/1] cd /tmp/tianshan-ws-build/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-ws-build/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[2/10] No install step for 'bootloader' +[3/10] cd /tmp/tianshan-ws-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-ws-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-ws-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[4/10] Completed 'bootloader' +[5/10] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[6/10] Linking C static library esp-idf/ts_webui/libts_webui.a +[7/10] Generating esp-idf/esp_system/ld/sections.ld +[8/10] Linking CXX executable TianShanOS.elf +[9/10] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-ws-build/build/TianShanOS.bin +[10/10] cd /tmp/tianshan-ws-build/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-ws-build/build/partition_table/partition-table.bin /tmp/tianshan-ws-build/build/TianShanOS.bin +TianShanOS.bin binary size 0x213450 bytes. Smallest app partition is 0x300000 bytes. 0xecbb0 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-ws-build/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-ws-build/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-ws-build/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-ws-build/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-ws-build/build/www.bin +or from the "/private/tmp/tianshan-ws-build/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/certificate.txt b/docs/repair/ws-subscriptions/reviewer-fixes/certificate.txt new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/certificate.txt @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/diff-check.txt b/docs/repair/ws-subscriptions/reviewer-fixes/diff-check.txt new file mode 100644 index 0000000..f132957 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/diff-check.txt @@ -0,0 +1,2 @@ +git diff --check +exit: 0 diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/final-manifest.json b/docs/repair/ws-subscriptions/reviewer-fixes/final-manifest.json new file mode 100644 index 0000000..cb9d1e2 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/final-manifest.json @@ -0,0 +1,94 @@ +{ + "created_at": "2026-09-25T03:25:21.772379+08:00", + "head": "35238b4645ae5e9e0e99555d4fb64080d945565c", + "branch": "fix/v0.5.2-reliability-and-prompts", + "baseline_archive_sha256": "e29238993bc5d1db199ad1f364a11b28bcf23b091f6c07676c5d7ce46e0f7204", + "patch_scope": "Production and test changes against frozen uncommitted baseline; evidence and report documents excluded.", + "changed_files": [ + "components/ts_core/ts_service/src/ts_service.c", + "components/ts_net/src/ts_http_server.c", + "components/ts_webui/include/ts_ws_subscriptions.h", + "components/ts_webui/include/ts_ws_transport.h", + "components/ts_webui/src/ts_webui_ws.c", + "components/ts_webui/src/ts_ws_subscriptions.c", + "components/ts_webui/src/ts_ws_transport.c", + "main/ts_core_init.c", + "tests/ws_subscriptions/README.md", + "tests/ws_subscriptions/run_reviewer.sh", + "tests/ws_subscriptions/run_reviewer_baseline.sh", + "tests/ws_subscriptions/stubs/platform.h", + "tests/ws_subscriptions/test_init.c", + "tests/ws_subscriptions/test_manager.c", + "tests/ws_subscriptions/test_reviewer.c", + "tests/ws_subscriptions/test_reviewer_core.c", + "tests/ws_subscriptions/test_reviewer_http.c", + "tests/ws_subscriptions/test_reviewer_service.c" + ], + "source_sha256": { + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_core/ts_service/src/ts_service.c": "326b3ab1d4a61eba8b9bf43af26039fc4562092cbea19709764104278c79ec2b", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/src/ts_http_server.c": "0c8449fb396246074ef9deb404b2d5f98610f4f22f3c1ce70bf2774711dbb6ad", + "components/ts_webui/CMakeLists.txt": "9a52c046ca47d6e19fa001796ed7469387566e4cfb176a85d55a5f1b96f2fcfa", + "components/ts_webui/include/ts_ws_subscriptions.h": "ab44ae214761c059ceebb993c61fa1ee8c0a8bc2b1a9b1bb19f864ea4dc534ea", + "components/ts_webui/include/ts_ws_transport.h": "f69df08ce9f21b89a00f6e8d7d74ec1430567053c46a150961f61bc8d20f9ec2", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_ws.c": "425e52b9eec4924c005c18f5bd3c182c50eba1722a21d9266615bc7026db36f7", + "components/ts_webui/src/ts_ws_subscriptions.c": "0782ccc9b76356d2a358e837a8f8cfa20f6aeb8f88b0f720d0ca0f037f4d5472", + "components/ts_webui/src/ts_ws_transport.c": "8cafd0c9313f5e07fff574a40292df599d73d695c00f3290a1573e0dbcd2166c", + "main/ts_core_init.c": "ad9b89b44eef49a72117197da3e2d44a0a9ba73cbf5d1a4c7c6a7e123ea41e1f", + "tests/prompts/ownership.browser.test.cjs": "1938411e7cc76ecc190b3469c58e58fd8aaa4a080ede60989190b4abd1147903", + "tests/ws_subscriptions/README.md": "e09376ae55908d07e523740c2ce8626de585c5ccb6c9f67290927bae4cf75857", + "tests/ws_subscriptions/run_baseline.sh": "2b5a8288cc2d94276588589eea6b45b8fb028fbb93c5911efff668b8d7d953c0", + "tests/ws_subscriptions/run_host.sh": "2a1aee658ec0c45fb94163d9671f72579cf8f15fb36532aeef4a5f1d4bfd90f9", + "tests/ws_subscriptions/run_reviewer.sh": "9b3ec0cae5ef734f5e9fb47acc630cd7eb36e6701bf716308c885a6162247fed", + "tests/ws_subscriptions/run_reviewer_baseline.sh": "6ea73543f64c6de65f59480300cf2d73ece85b798a7a430df5b55f2adae1bb96", + "tests/ws_subscriptions/stubs/esp_err.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_heap_caps.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_http_server.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/esp_timer.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/FreeRTOS.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/queue.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/semphr.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/freertos/task.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/platform.h": "81819518855ce83e8001669d262a7348a6da2250f620baad78a070370543f606", + "tests/ws_subscriptions/stubs/ts_api.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_event.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_log.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/stubs/ts_webui.h": "f7223107a5221902365ce989ae1b9483cef3925e75c0f739e439a4ed432875cc", + "tests/ws_subscriptions/test_baseline.c": "1197573bdf34c4bb7d2aa86f9742ae568199db3a6927211081251345c5070442", + "tests/ws_subscriptions/test_event.c": "88273dfb16120f29254912729dbceb9cefe025902b5d8e1fb4602f5b09500636", + "tests/ws_subscriptions/test_init.c": "4f7995f2e8c39a6247585e2436475d6ec6473c40479c910a54fa0cd3bf7e3f7a", + "tests/ws_subscriptions/test_lifecycle.c": "187359b892e11b98d3491f3ee60aac5cda9e157c65fbd262fe0fe466d5f943d3", + "tests/ws_subscriptions/test_manager.c": "0cb62636a0f35b57ab997629d1e2c7d7fe349029cc317379db2d4b688924e8b8", + "tests/ws_subscriptions/test_reviewer.c": "14ef95d866c0b9f38ff2c2350fe37d86e584c6ebc4dc9437ba52feb67241da19", + "tests/ws_subscriptions/test_reviewer_core.c": "7669567ad82171ae32102779e4fc98c4b88871f9e9f761600a21623378882ef2", + "tests/ws_subscriptions/test_reviewer_http.c": "2b9696ac9dd86be96db383392d3bcf61f81a5ab2e881933d767aad8f91d30c00", + "tests/ws_subscriptions/test_reviewer_service.c": "3fa82db0882b90d69450ddcd7a50e5904ae60e2cab8e62ea11656ac4c21e2890" + }, + "evidence_sha256": { + "README.md": "a9b675336a8637e54cca9e2dd4356a7fe1803025ff726a7d489f4968a22bee1a", + "baseline-r1-r3.txt": "244db79e80a29d579f48ad66c6e3e74da9524acaaabafb7ad964b349cb4e3035", + "baseline-r4-r5.txt": "282b5c5d52b301118c4f07879144172af159cc7ebdb1bfea50b1f29f583979a6", + "baseline-replay.txt": "02e424e309b7e84ea2c0d98e026de622552e23e3c93dcb4baac2b1d164b320be", + "baseline.json": "b5158a0060364bba7a59f52a2344352798c57c879ca426db93bc3e1f7037c19e", + "browser.txt": "1f2a36da815ad8d41c371a36cce0bb1e4b6ab2ac99641521eef291c49e151f9a", + "build.txt": "730d813c135f251f91fd4c2d51979588e075c2f729a63b77e79a372bd7ecd217", + "certificate.txt": "d3e446956791a6ec5d2a6b2235eaffcc0c45cb6ed4f2cd32eae130bb57f7dd21", + "diff-check.txt": "2d0582f56d02ef3b69ef68368f867be3298b1bf7ee9ffb8ae2d05378c7cd097d", + "host.txt": "fde8084a35208ab61ec026c7c1bc29578b75b5b92584c5b70f7a430bd1a9a907", + "pre-fix-source.tar.gz": "e29238993bc5d1db199ad1f364a11b28bcf23b091f6c07676c5d7ce46e0f7204", + "prompts.txt": "13a026fc727ee2447f22bcde8eaecaa2e1f308d249d3ed8419b50d1c8d58a08a", + "resources.txt": "8e8da3007131f3d7deced079713ea22e7bdf8fca21e07b4107c1a89f8efdc9a1", + "reviewer-fixes.patch": "e4a109015fce0f90d6fb0c5809636515c4eef3243f51629ee941e83776ed39a0", + "reviewer-tests.txt": "e1a7c52fb704d7010a8efd00488f46738f22ea275cd26cb59d49c8d0b316c60c", + "runtime.txt": "f300e6d09f01acebc6d725ea5377e878f60d09db17464819d9306a0156817e96" + }, + "build_binaries": { + "/tmp/tianshan-ws-build/build/TianShanOS.bin": "2fc94159f5db373bc8a709aeaab1257addff10fe2e72decb88d8619b0f72978e", + "/tmp/tianshan-ws-build/build/www.bin": "cdce507bebb727bd65136aa8d3687d9d09651c1f1ea2286fb3fe2e87fa4f30c5", + "/tmp/tianshan-ws-build/build/ota_data_initial.bin": "7d2c7ac4888bfd75cd5f56e8d61f69595121183afc81556c876732fd3782c62f" + } +} diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/host.txt b/docs/repair/ws-subscriptions/reviewer-fixes/host.txt new file mode 100644 index 0000000..377bb50 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/host.txt @@ -0,0 +1,25 @@ +PASS T01 T02 T05 T06 T07 T08: demand, independent intervals, targeted fanout +PASS T09 T12 T16: shared batch, old revision cannot send or update new state +PASS T11 T14: standalone info, queued delivery cannot cross fd reuse +PASS T13: cancellation during API skips remaining metrics +PASS T17 T19 T20: queue failure backoff, completion-before-return ownership +PASS T23: ordered operation events own borrowed data +PASS T10 T34: interval validation and nonzero capped monotonic waits +PASS T15 T27 T28: no second HTTP owner, reused handle epoch isolation, stop timeout retains live resources and retries +PASS T27 T30: stop during API rejects new instance; worker/HTTPD self-wait refused +PASS T21 T22: allocation failure sweep across production JSON/TX paths; per-call results freed; allocation baseline restored +PASS T24 T25: bounded non-NUL event parse, retained paced events, original global recipient set +PASS T23: bounded event FIFO full is counted, accepted results remain ordered +PASS T26: task and partial handler registration rollback permit retry +PASS T29 T33: repeated lifecycle and notification at wait boundary +PASS T18 T19 T20: bounded slots/bytes, reserved global capacity, delayed completion cadence, separate queue/send counters +PASS T09 T14 T16: snapshot-before-collection and send-before-completion barriers with resubscribe/fd reuse +PASS T17 T28: HTTP handler barrier publication, timeout retention, single retry and callback-before-return +PASS T04 T20 T21: business-error results freed; send failure shuts down only the pinned session and invalidates demand +PASS cross matrix: 4 barriers x 5 mutations (cancel, resubscribe, disconnect, fd reuse, stop/restart exclusion); restart succeeds after every drain +PASS T18 configured 32-service escaped-name fixture: 9991 bytes within 32768-byte frame budget +PASS T32: self unregister, selected-node retirement, in-flight synchronous drain, unrelated handler retained +PASS actual HTTP/WebUI stop/deinit: hook timeout, HTTPD failure, self-stop rejection, truthful state, retained ownership and retry +PASS actual WebSocket stop: manager/barrier failures propagate, active SSH creation/execution retained, poller timeout retained, transport drain retry and HTTPD self-wait rejected +PASS actual SSH creation wrappers: concurrent builder rejected and stop admission closes without invoking the remote-operation implementation +PASS actual WebSocket initializer: server/transport/manager/two mutexes/buffer/URI/power-handler failures are not reported as success; duplicate/retry-state guards diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/pre-fix-source.tar.gz b/docs/repair/ws-subscriptions/reviewer-fixes/pre-fix-source.tar.gz new file mode 100644 index 0000000..21ab972 Binary files /dev/null and b/docs/repair/ws-subscriptions/reviewer-fixes/pre-fix-source.tar.gz differ diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/prompts.txt b/docs/repair/ws-subscriptions/reviewer-fixes/prompts.txt new file mode 100644 index 0000000..816cda8 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/prompts.txt @@ -0,0 +1,51 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (16.651792ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (5.999375ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (8.006625ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.503042ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (6.142459ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (5.915541ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (5.980375ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.776417ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (5.7825ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.57925ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (6.121667ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.706292ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (5.430833ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (6.246042ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.978ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.858916ms) +✔ en-US: toast timer replacement, priority, safe multiline text (6.059792ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (6.275083ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.685209ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (6.047084ms) +✔ en-US: file names are text; upload/verification/apply remain separate (6.192917ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (8.40425ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.940083ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.420792ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (5.3055ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.814625ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (4.759583ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (6.831833ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.7375ms) +✔ en-US: upload and download aggregates cover all success and all failure (5.564375ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (5.046208ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.930334ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.877542ms) +✔ zh-CN: unknown stop result never escalates to forced termination (6.941458ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (4.762541ms) +✔ en-US: unknown stop result never escalates to forced termination (5.425042ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.669417ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.100583ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 271.015166 diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/resources.txt b/docs/repair/ws-subscriptions/reviewer-fixes/resources.txt new file mode 100644 index 0000000..3335ceb --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/resources.txt @@ -0,0 +1,21 @@ +/Users/massif/TianshanOS/components/ts_webui/src/ts_webui_ws.c:385:13:handle_ssh_connect 336 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_subscriptions.c:149:13:collect_batch 176 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_subscriptions.c:197:13:run_batch 3360 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_subscriptions.c:299:13:telemetry_worker 32 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:496:11:ts_ws_reserve 112 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:529:6:ts_ws_reserved_json 32 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:540:11:ts_ws_reserved_text 32 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:548:11:ts_ws_reserved_submit 80 static +/Users/massif/TianshanOS/components/ts_webui/src/ts_ws_transport.c:570:11:ts_ws_result_broadcast 304 static +ts_webui_ws.o +00000000 00000088 b s_exec_terminal +00000000 00000004 b s_server +00000000 00000088 b s_ssh_terminal +ts_ws_subscriptions.o +00000000 00000460 b s_events +00000000 00000a00 b s_subs +ts_ws_transport.o +00000000 00001180 b s_deliveries +00000000 00000040 b s_log_revisions +00000000 000000a0 b s_messages +00000000 00000028 b s_server diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/reviewer-fixes.patch b/docs/repair/ws-subscriptions/reviewer-fixes/reviewer-fixes.patch new file mode 100644 index 0000000..fea0f80 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/reviewer-fixes.patch @@ -0,0 +1,1830 @@ +--- a/components/ts_core/ts_service/src/ts_service.c ++++ b/components/ts_core/ts_service/src/ts_service.c +@@ -143,7 +143,8 @@ + ESP_LOGI(TAG, "Deinitializing service management..."); + + // 停止所有服务 +- ts_service_stop_all(); ++ esp_err_t ret = ts_service_stop_all(); ++ if (ret != ESP_OK) return ret; + + xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); + +@@ -380,7 +381,8 @@ + if (service->def.phase == phase && + service->state == TS_SERVICE_STATE_RUNNING) { + xSemaphoreGive(s_svc_ctx.mutex); +- ts_service_stop(service); ++ esp_err_t ret = ts_service_stop(service); ++ if (ret != ESP_OK) return ret; /* keep dependencies and registry for retry */ + xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); + } + service = service->next; +--- a/components/ts_net/src/ts_http_server.c ++++ b/components/ts_net/src/ts_http_server.c +@@ -128,6 +128,10 @@ + + static esp_err_t http_handler_wrapper(httpd_req_t *req) + { ++ if(s_stopping && req->method!=HTTP_GET) { ++ httpd_resp_set_status(req,"503 Service Unavailable"); ++ return httpd_resp_sendstr(req,"Service is stopping"); ++ } + ts_http_route_t *route = (ts_http_route_t *)req->user_ctx; + if (!route || !route->handler) { + httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "No handler"); +--- a/components/ts_webui/include/ts_ws_subscriptions.h ++++ b/components/ts_webui/include/ts_ws_subscriptions.h +@@ -29,6 +29,8 @@ + * @brief 反初始化订阅管理器 + */ + esp_err_t ts_ws_subscriptions_deinit(void); ++esp_err_t ts_ws_subscriptions_pause(void); ++esp_err_t ts_ws_subscriptions_drain(void); + + /** + * @brief 处理订阅请求 +--- a/components/ts_webui/include/ts_ws_transport.h ++++ b/components/ts_webui/include/ts_ws_transport.h +@@ -7,6 +7,8 @@ + #define TS_WS_TOPIC_TX_SLOTS 32 + #define TS_WS_TX_SLOTS (TS_WS_TOPIC_TX_SLOTS + TS_WS_CONNECTIONS) + #define TS_WS_MESSAGE_SLOTS 8 ++#define TS_WS_ALL_MESSAGE_SLOTS (TS_WS_MESSAGE_SLOTS + 2) ++#define TS_WS_ALL_TX_SLOTS (TS_WS_TX_SLOTS + 2 * TS_WS_CONNECTIONS) + #define TS_WS_FRAME_BYTES 32768 + #define TS_WS_LEGACY_BYTES (512 * 1024) + #define TS_WS_TOTAL_BYTES (1024 * 1024) +@@ -82,3 +84,26 @@ + void ts_ws_transport_flush(void); + bool ts_ws_transport_needs_flush(void); + void ts_ws_transport_cancel_topics(void); ++ ++/* A bounded reservation owns actual payload bytes and destination descriptors. ++ * No API collection / accepted result producer may start before it succeeds. */ ++#define TS_WS_RESERVATION_TARGETS ((TS_WS_CONNECTIONS > TS_WS_TOPIC_TX_SLOTS) ? TS_WS_CONNECTIONS : TS_WS_TOPIC_TX_SLOTS) ++typedef struct { ++ ts_ws_message_t *message; ++ unsigned count; ++ int slots[TS_WS_RESERVATION_TARGETS]; ++} ts_ws_reservation_t; ++esp_err_t ts_ws_reserve(const ts_ws_peer_t *peers, unsigned count, bool result, ++ size_t bytes, ts_ws_reservation_t *reservation); ++bool ts_ws_reserved_json(ts_ws_reservation_t *r, const char *topic, const cJSON *data, int64_t timestamp); ++esp_err_t ts_ws_reserved_text(ts_ws_reservation_t *r, const char *text); ++esp_err_t ts_ws_reserved_submit(ts_ws_reservation_t *r, unsigned index, ++ uint64_t revision, uint64_t delivery, ts_ws_delivery_check_t check, ts_ws_delivery_done_t done); ++void ts_ws_reservation_release(ts_ws_reservation_t *r); ++unsigned ts_ws_peer_snapshot(ts_ws_peer_t *peers, unsigned capacity); ++ ++/* Preserve global result recipients at completion, with capacity owned at admission. */ ++esp_err_t ts_ws_result_reserve(size_t bytes, ts_ws_reservation_t *r); ++esp_err_t ts_ws_result_broadcast(ts_ws_reservation_t *r, const char *text); ++ ++uint32_t ts_ws_transport_retry_ms(void); +--- a/components/ts_webui/src/ts_webui_ws.c ++++ b/components/ts_webui/src/ts_webui_ws.c +@@ -80,6 +80,10 @@ + static atomic_int s_ssh_client_fd = -1; + static atomic_bool s_ssh_running = false; + static atomic_bool s_ssh_poll_alive; ++enum { SSH_IDLE, SSH_STARTING, SSH_READY, SSH_TERMINAL }; ++static atomic_uint s_ssh_state, s_ssh_generation, s_ssh_result_pending; ++static ts_ws_reservation_t s_ssh_terminal; ++static ts_ws_reservation_t s_exec_terminal; + + /* SSH Exec 流式执行状态 */ + static ts_ssh_session_t s_exec_session = NULL; +@@ -95,16 +99,32 @@ + + /* 日志回调句柄 */ + static ts_log_callback_handle_t s_log_callback_handle = NULL; +-static volatile bool s_log_streaming_enabled = false; ++static atomic_bool s_log_streaming_enabled = false; + + /* 日志级别名称映射 */ + static const char *s_level_names[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"}; + + /* 前向声明 */ + static void update_log_stream_state(void); ++esp_err_t ts_webui_log_stream_enable(bool enable); + esp_err_t ts_webui_ws_stop(httpd_handle_t server); + void ts_webui_ws_stopped(httpd_handle_t server); + static bool has_log_clients(void); ++ ++/* HTTPD owner updates role and log generation together. Old queued logs cannot ++ * regain eligibility after a later subscribe on the same connection. */ ++static void set_client_role(ts_ws_peer_t peer, ws_client_type_t type, ts_log_level_t level) ++{ ++ ts_ws_peer_t current; ++ if (!ts_ws_peer_get(peer.server, peer.fd, ¤t) || !ts_ws_peer_equal(peer,current)) return; ++ for (int i=0;i= 0) { + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == s_ssh_client_fd) { +- s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; ++ set_client_role(s_ssh_peer, WS_CLIENT_TYPE_TERMINAL, TS_LOG_NONE); + break; + } + } + } ++ if(s_ssh_state==SSH_READY) ssh_send_status("closed","SSH session closed"); + s_ssh_client_fd = -1; ++ ts_ws_reservation_release(&s_ssh_terminal); + + TS_LOGD(TAG, "SSH session cleaned up"); + } +@@ -324,8 +384,12 @@ + /* 处理 SSH Shell 连接请求 */ + static void handle_ssh_connect(httpd_req_t *req, cJSON *params) + { ++ if (s_ssh_result_pending) { ++ ssh_request_error(req,"Previous SSH result is still pending"); ++ return; ++ } + if (s_ssh_poll_alive) { +- ssh_send_status("error", "Another SSH session is active"); ++ ssh_request_error(req, "Another SSH session is active"); + return; + } + +@@ -333,7 +397,7 @@ + + // 检查是否已有 SSH 会话 + if (s_ssh_session != NULL) { +- ssh_send_status("error", "Another SSH session is active"); ++ ssh_request_error(req, "Another SSH session is active"); + return; + } + +@@ -344,7 +408,7 @@ + cJSON *password = cJSON_GetObjectItem(params, "password"); + + if (!host || !cJSON_IsString(host) || !user || !cJSON_IsString(user)) { +- ssh_send_status("error", "Missing host or user"); ++ ssh_request_error(req, "Missing host or user"); + return; + } + +@@ -353,6 +417,13 @@ + + TS_LOGD(TAG, "SSH connect: %s@%s:%d", user->valuestring, host->valuestring, ssh_port); + ++ ts_ws_peer_t peer=*(ts_ws_peer_t *)req->sess_ctx; ++ if(s_ssh_generation==UINT32_MAX || ts_ws_reserve(&peer,1,true,4096,&s_ssh_terminal)!=ESP_OK) { ++ ssh_request_error(req,"SSH result delivery capacity unavailable"); ++ return; ++ } ++ s_ssh_generation++; ++ s_ssh_state=SSH_STARTING; + // 设置 SSH 客户端 fd + s_ssh_peer = *(ts_ws_peer_t *)req->sess_ctx; + s_ssh_client_fd = fd; +@@ -360,13 +431,16 @@ + // 更新客户端类型 + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { +- s_clients[i].type = WS_CLIENT_TYPE_SSH_SHELL; ++ set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_SSH_SHELL, TS_LOG_NONE); + break; + } + } + + // 发送连接中状态 +- ssh_send_status("connecting", "Connecting to SSH server..."); ++ if(ssh_send_status("connecting", "Connecting to SSH server...")!=ESP_OK) { ++ ssh_send_status("error","SSH connection status delivery failed"); ++ ssh_cleanup();return; ++ } + + // 配置 SSH + ts_ssh_config_t config = TS_SSH_DEFAULT_CONFIG(); +@@ -408,15 +482,28 @@ + return; + } + +- // 发送连接成功状态 +- ssh_send_status("connected", "SSH shell ready"); +- + // 启动轮询任务(栈需要足够大以容纳 libssh2 缓冲区,使用 PSRAM) + s_ssh_running = true; + s_ssh_poll_alive = true; + if (xTaskCreateWithCaps(ssh_poll_task, "ssh_poll", 4096, NULL, 5, NULL, MALLOC_CAP_SPIRAM) != pdPASS) { + s_ssh_poll_alive = false; + ssh_send_status("error", "Failed to create SSH session"); ++ ssh_cleanup(); ++ return; ++ } ++ /* A created task alone is not readiness: the current shell must still be ++ * active. The poller cannot emit output/closed until STARTING has ended. */ ++ if(!ts_ssh_shell_is_active(s_ssh_shell)) { ++ ssh_send_status("error","SSH shell closed during startup"); ++ ssh_cleanup();return; ++ } ++ unsigned expected=SSH_STARTING; ++ if(!atomic_compare_exchange_strong(&s_ssh_state,&expected,SSH_READY)) { ++ ssh_cleanup();return; ++ } ++ esp_err_t ready=ssh_send_status("connected","SSH shell ready"); ++ if(ready!=ESP_OK && s_ssh_state==SSH_READY) { ++ ssh_send_status("error","SSH readiness delivery failed"); + ssh_cleanup(); + } + } +@@ -645,7 +732,7 @@ + // 设置为终端客户端 + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { +- s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; ++ set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_TERMINAL, TS_LOG_NONE); + break; + } + } +@@ -725,7 +812,6 @@ + + static esp_err_t ws_handler(httpd_req_t *req) + { +- if (s_ws_stopping) return ESP_ERR_INVALID_STATE; + if (req->method == HTTP_GET) { + TS_LOGD(TAG, "WebSocket handshake"); + // 初次连接时添加为事件客户端 +@@ -787,6 +873,17 @@ + if (msg) { + cJSON *type = cJSON_GetObjectItem(msg, "type"); + if (type && cJSON_IsString(type)) { ++ /* Keep existing connections (and heartbeat) alive while results drain. ++ * Reject new work with a protocol error, not an HTTPD session error. */ ++ if(s_ws_stopping && strcmp(type->valuestring,"ping") && ++ strcmp(type->valuestring,"unsubscribe")) { ++ const char *error="{\"type\":\"error\",\"message\":\"Service is stopping\"}"; ++ httpd_ws_frame_t frame={.type=HTTPD_WS_TYPE_TEXT,.payload=(uint8_t*)error,.len=strlen(error)}; ++ esp_err_t result=httpd_ws_send_frame(req,&frame); ++ cJSON_Delete(msg); ++ return result; ++ } ++ + TS_LOGD(TAG, "WS msg type=%s from fd=%d", type->valuestring, httpd_req_to_sockfd(req)); + + if (strcmp(type->valuestring, "ping") == 0) { +@@ -879,8 +976,7 @@ + // 恢复为普通事件客户端 + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { +- s_clients[i].type = WS_CLIENT_TYPE_EVENT; +- ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, -1); ++ set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_EVENT, TS_LOG_NONE); + break; + } + } +@@ -931,9 +1027,7 @@ + bool client_found = false; + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { +- s_clients[i].type = WS_CLIENT_TYPE_LOG; +- s_clients[i].log_min_level = min_level; +- ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, min_level); ++ set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_LOG, min_level); + client_found = true; + TS_LOGI(TAG, "Client %d subscribed to logs (minLevel=%d)", i, min_level); + break; +@@ -965,8 +1059,7 @@ + int fd = httpd_req_to_sockfd(req); + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { +- s_clients[i].type = WS_CLIENT_TYPE_EVENT; +- ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, -1); ++ set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_EVENT, TS_LOG_NONE); + break; + } + } +@@ -981,8 +1074,7 @@ + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd && + s_clients[i].type == WS_CLIENT_TYPE_LOG) { +- s_clients[i].log_min_level = (ts_log_level_t)level->valueint; +- ts_ws_peer_log_level(*(ts_ws_peer_t *)req->sess_ctx, level->valueint); ++ set_client_role(*(ts_ws_peer_t *)req->sess_ctx, WS_CLIENT_TYPE_LOG, (ts_log_level_t)level->valueint); + break; + } + } +@@ -1146,21 +1238,26 @@ + { + if (ts_ws_transport_in_context() || ts_event_in_callback()) return ESP_ERR_INVALID_STATE; + s_ws_stopping = true; +- esp_err_t ret = ts_ws_subscriptions_deinit(); ++ esp_err_t ret = ts_ws_subscriptions_pause(); + if (ret != ESP_OK) return ret; + ret = ts_ws_transport_quiesce(server, 6000); + if (ret != ESP_OK) return ret; ++ /* The worker still sends results even when this attempt returns busy. */ ++ if (s_exec_creators || s_exec_running) return ESP_ERR_INVALID_STATE; ++ ssh_cleanup(); ++ if (s_ssh_poll_alive) return ESP_ERR_TIMEOUT; + if (s_power_event_handle) { + ret = ts_event_unregister_sync(s_power_event_handle, 6000); + if (ret != ESP_OK && ret != ESP_ERR_NOT_FOUND) return ret; + s_power_event_handle = NULL; + } +- /* Do not destroy a running remote operation or replay it. Keep HTTPD alive +- * and return busy; the control caller can retry after its normal completion. */ +- if (s_exec_creators || s_exec_running) return ESP_ERR_INVALID_STATE; +- ssh_cleanup(); +- if (s_ssh_poll_alive) return ESP_ERR_TIMEOUT; +- return ts_ws_transport_stop(server, 6000); ++ ret = ts_webui_log_stream_enable(false); ++ if (ret != ESP_OK) return ret; ++ ret = ts_ws_subscriptions_drain(); ++ if (ret != ESP_OK) return ret; ++ ret = ts_ws_transport_stop(server, 6000); ++ if (ret != ESP_OK) return ret; ++ return ts_ws_subscriptions_deinit(); + } + + void ts_webui_ws_stopped(httpd_handle_t server) +@@ -1262,21 +1359,20 @@ + */ + esp_err_t ts_webui_log_stream_enable(bool enable) + { +- if (enable && !s_log_callback_handle) { +- // 注册日志回调 (min_level=TS_LOG_VERBOSE, 接收所有级别) +- esp_err_t ret = ts_log_add_callback(log_ws_callback, TS_LOG_VERBOSE, NULL, &s_log_callback_handle); +- if (ret != ESP_OK) { +- TS_LOGE(TAG, "Failed to register log callback: %s", esp_err_to_name(ret)); +- return ret; +- } +- s_log_streaming_enabled = true; +- TS_LOGI(TAG, "Log streaming enabled (receiving all levels)"); +- } else if (!enable && s_log_callback_handle) { +- // 移除日志回调 +- s_log_streaming_enabled = false; +- ts_log_remove_callback(s_log_callback_handle); +- s_log_callback_handle = NULL; +- TS_LOGI(TAG, "Log streaming disabled"); ++ if(enable) { ++ if(!s_log_callback_handle) { ++ esp_err_t ret=ts_log_add_callback(log_ws_callback,TS_LOG_VERBOSE,NULL,&s_log_callback_handle); ++ if(ret!=ESP_OK)return ret; ++ } ++ /* A failed remove retains the handle; resubscribe reuses it. */ ++ s_log_streaming_enabled=true; ++ } else { ++ s_log_streaming_enabled=false; ++ if(s_log_callback_handle) { ++ esp_err_t ret=ts_log_remove_callback(s_log_callback_handle); ++ if(ret!=ESP_OK)return ret; ++ s_log_callback_handle=NULL; ++ } + } + return ESP_OK; + } +@@ -1636,6 +1732,18 @@ + } + } + ++/* Every accepted streamed command owns one result reservation. Ordinary output ++ * cannot consume it. Oversize/encoding failure is reported, never as success. */ ++static void ssh_exec_terminal_publish(const char *json,uint32_t session_id) ++{ ++ char fallback[192]; ++ snprintf(fallback,sizeof(fallback),"{\"type\":\"ssh_exec_error\",\"session_id\":%lu,\"error\":\"SSH result delivery failed; result is unknown\"}",(unsigned long)session_id); ++ esp_err_t ret=ts_ws_result_broadcast(&s_exec_terminal,json?json:fallback); ++ if(ret==ESP_ERR_INVALID_SIZE)ret=ts_ws_result_broadcast(&s_exec_terminal,fallback); ++ if(ret!=ESP_OK)TS_LOGW(TAG,"SSH terminal result rejected: %s",esp_err_to_name(ret)); ++ ts_ws_reservation_release(&s_exec_terminal); ++} ++ + /* SSH Exec 任务 */ + static void ssh_exec_task(void *arg) + { +@@ -1670,7 +1778,7 @@ + cJSON_AddStringToObject(msg, "error", "Failed to load SSH key"); + char *json = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); +- if (json) { ts_webui_broadcast(json); free(json); } ++ ssh_exec_terminal_publish(json,session_id); free(json); + goto cleanup; + } + } +@@ -1685,7 +1793,7 @@ + cJSON_AddStringToObject(msg, "error", "Failed to create SSH session"); + char *json = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); +- if (json) { ts_webui_broadcast(json); free(json); } ++ ssh_exec_terminal_publish(json,session_id); free(json); + goto cleanup; + } + +@@ -1700,7 +1808,7 @@ + cJSON_AddStringToObject(msg, "error", err ? err : "Connection failed"); + char *json = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); +- if (json) { ts_webui_broadcast(json); free(json); } ++ ssh_exec_terminal_publish(json,session_id); free(json); + goto cleanup; + } + +@@ -1967,7 +2075,7 @@ + + char *json = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); +- if (json) { ts_webui_broadcast(json); free(json); } ++ ssh_exec_terminal_publish(json,session_id); free(json); + } + + /* 释放提取的值 */ +@@ -2109,7 +2217,14 @@ + uint32_t *session_id) + { + unsigned creators = atomic_fetch_add(&s_exec_creators, 1); +- esp_err_t ret = (creators || s_ws_stopping) ? ESP_ERR_INVALID_STATE : ts_webui_ssh_exec_start_impl(host, port, user, keyid, password, command, session_id); ++ esp_err_t ret=ESP_ERR_INVALID_STATE; ++ if(!creators && !s_ws_stopping && !s_exec_running) { ++ ret=ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal); ++ if(ret==ESP_OK) { ++ ret=ts_webui_ssh_exec_start_impl(host, port, user, keyid, password, command, session_id); ++ if(ret!=ESP_OK)ts_ws_reservation_release(&s_exec_terminal); ++ } ++ } + atomic_fetch_sub(&s_exec_creators, 1); + return ret; + } +@@ -2325,7 +2440,14 @@ + uint32_t *session_id) + { + unsigned creators = atomic_fetch_add(&s_exec_creators, 1); +- esp_err_t ret = (creators || s_ws_stopping) ? ESP_ERR_INVALID_STATE : ts_webui_ssh_exec_start_ex_impl(host, port, user, keyid, password, command, options, session_id); ++ esp_err_t ret=ESP_ERR_INVALID_STATE; ++ if(!creators && !s_ws_stopping && !s_exec_running) { ++ ret=ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal); ++ if(ret==ESP_OK) { ++ ret=ts_webui_ssh_exec_start_ex_impl(host, port, user, keyid, password, command, options, session_id); ++ if(ret!=ESP_OK)ts_ws_reservation_release(&s_exec_terminal); ++ } ++ } + atomic_fetch_sub(&s_exec_creators, 1); + return ret; + } +--- a/components/ts_webui/src/ts_ws_subscriptions.c ++++ b/components/ts_webui/src/ts_ws_subscriptions.c +@@ -27,7 +27,7 @@ + static const char *metrics[] = {"system.cpu","system.memory","system.info", + "network.status","power.status","fan.status","service.list"}; + static const char *fields[] = {"cpu","memory","info","network","power","fan","services"}; +-typedef enum { OFF, STARTING, RUNNING, STOPPING } lifecycle_t; ++typedef enum { OFF, STARTING, RUNNING, DRAINING, STOPPING } lifecycle_t; + typedef struct { + ts_ws_peer_t peer; + uint64_t revision, pending; +@@ -55,6 +55,8 @@ + static TaskHandle_t s_worker; + static unsigned s_entries, s_outstanding; + static uint64_t s_sequence; ++static unsigned s_topic_cursor, s_subscription_cursor; ++static int64_t s_allocation_retry_at; + static subscription_t s_subs[MAX_SUBSCRIPTIONS]; + static event_item_t s_events[EVENT_SLOTS]; + static ts_event_handler_handle_t s_handlers[3]; +@@ -79,10 +81,10 @@ + if (name) for (unsigned i=0;ipending == delivery; ++ bool ok = (s_state == RUNNING || s_state == DRAINING) && s && s->pending == delivery; + portEXIT_CRITICAL(&s_lock); + return ok; + } +@@ -144,7 +146,7 @@ + topics[targets[i].topic].metric == (int)metric) && delivery_valid(targets[i].revision,targets[i].delivery)) return true; + return false; + } +-static void collect_batch(target_t *targets, unsigned n) ++static void collect_batch(target_t *targets, unsigned n, ts_ws_reservation_t *reserved) + { + cJSON *data[7] = {0}; + for (unsigned i=0;i<7;i++) { +@@ -171,13 +173,22 @@ + } + if(ok && any) payload=dashboard; + } else payload=data[topics[topic].metric]; +- if(payload) m=ts_ws_message_json(topics[topic].name,payload,esp_timer_get_time()/1000000); ++ if(payload && ts_ws_reserved_json(&reserved[topic],topics[topic].name,payload,esp_timer_get_time()/1000000)) m=reserved[topic].message; + portENTER_CRITICAL(&s_lock); + s_stats.batches[topic]++; if(m) s_stats.serialized[topic]++; + portEXIT_CRITICAL(&s_lock); + } +- for(unsigned i=0;iactive && s->topic<8 && !s->pending && now>=s->next_attempt && reserve(s,&targets[n])) n++; +- } +- portEXIT_CRITICAL(&s_lock); +- if(n) { TS_WS_TEST_POINT("snapshot"); collect_batch(targets,n); } ++ unsigned first=s_topic_cursor; ++ for(unsigned turn=0;turn<8;turn++) { ++ unsigned topic=(first+turn)%8; ++ ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ unsigned slots[TS_WS_CONNECTIONS], count=0; ++ uint64_t revisions[TS_WS_CONNECTIONS]; ++ capacity=ts_ws_transport_capacity(); ++ portENTER_CRITICAL(&s_lock); ++ if(s_state==RUNNING) for(unsigned j=0;jactive && sub->topic==topic && !sub->pending && now>=sub->next_attempt) { ++ peers[count]=sub->peer;slots[count]=i;revisions[count++]=sub->revision; ++ } ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if(!count || nowactive && sub->revision==revisions[j] && !sub->pending && reserve(sub,&targets[n])) n++; ++ else targets[n++]=(target_t){.topic=topic}; ++ } ++ s_subscription_cursor=(slots[count-1]+1)%MAX_SUBSCRIPTIONS; ++ portEXIT_CRITICAL(&s_lock); ++ s_topic_cursor=(topic+1)%8; ++ } ++ if(n) { TS_WS_TEST_POINT("snapshot"); collect_batch(targets,n,reserved); } + /* Event FIFO per subscription. A slow target does not hold up other targets. + * Different operation results never overwrite each other. */ + for(unsigned slot=0;slotready) { + for(unsigned j=0;jtargets[j]) { + subscription_t *s=find_revision(e->targets[j]); +- if(!s || s_state!=RUNNING) {e->targets[j]=0;continue;} ++ if(!s || (s_state!=RUNNING && s_state!=DRAINING)) {e->targets[j]=0;continue;} + bool earlier=false; + for(unsigned k=0;korder) + for(unsigned l=0;lrevision) earlier=true; +@@ -237,7 +278,7 @@ + } + static TickType_t next_wait(void) + { +- if(ts_ws_transport_needs_flush()) return 1; ++ if(ts_ws_transport_needs_flush()) return wait_ticks((int64_t)ts_ws_transport_retry_ms()*1000); + int64_t now=esp_timer_get_time(), nearest=INT64_MAX; + unsigned capacity=ts_ws_message_capacity() ? ts_ws_transport_capacity() : 0; + portENTER_CRITICAL(&s_lock); +@@ -252,6 +293,7 @@ + if(nearest==INT64_MAX) s_stats.idle_wait++; + if(!capacity && nearest!=INT64_MAX) {nearest=after_ms(now,1000);s_stats.capacity_wait++;} + portEXIT_CRITICAL(&s_lock); ++ if(nearest!=INT64_MAX && nearest=deadline) return ESP_ERR_TIMEOUT; ++ vTaskDelay(1); ++ } + } + esp_err_t ts_ws_subscriptions_deinit(void) + { +@@ -350,7 +427,7 @@ + } + ts_ws_peer_t current; + if(!ts_ws_peer_get(peer.server,peer.fd,¤t)||!ts_ws_peer_equal(peer,current))return ESP_ERR_INVALID_STATE; +- if(!enter()) return ESP_ERR_INVALID_STATE; ++ if(!enter(false)) return ESP_ERR_INVALID_STATE; + int64_t now=esp_timer_get_time(); + esp_err_t ret=ESP_ERR_NO_MEM; + portENTER_CRITICAL(&s_lock); +@@ -374,7 +451,7 @@ + esp_err_t ts_ws_unsubscribe(ts_ws_peer_t peer,const char *topic) + { + int id=topic_id(topic);if(id<0)return ESP_ERR_NOT_FOUND; +- if(!enter())return ESP_ERR_INVALID_STATE; ++ if(!enter(true))return ESP_ERR_INVALID_STATE; + esp_err_t ret=ESP_ERR_NOT_FOUND; + portENTER_CRITICAL(&s_lock); + for(unsigned i=0;ihandle == s_server.handle && s_sequence != UINT64_MAX) { + for (unsigned i = 0; i < TS_WS_CONNECTIONS; ++i) if (!s_peers[i].connection) { + *ctx = (ts_ws_peer_t){req->handle, s_server.epoch, ++s_sequence, httpd_req_to_sockfd(req)}; +- s_peers[i] = *ctx; s_log_levels[i] = -1; *peer = *ctx; ret = ESP_OK; break; ++ s_peers[i] = *ctx; s_log_levels[i] = -1; s_log_revisions[i] = 0; *peer = *ctx; ret = ESP_OK; break; + } + } + portEXIT_CRITICAL(&s_lock); +@@ -126,12 +128,13 @@ + req->free_ctx = session_free; /* RST, LRU and httpd_stop also release this. */ + return ESP_OK; + } +-static ts_ws_message_t *message_alloc(size_t capacity, bool telemetry) ++static ts_ws_message_t *message_alloc(size_t capacity, unsigned kind) + { + ts_ws_message_t *m = NULL; + portENTER_CRITICAL(&s_lock); +- for (unsigned i = telemetry ? 0 : TS_WS_MESSAGE_SLOTS - 2; capacity <= TS_WS_TOTAL_BYTES - s_tx_stats.bytes && +- i < TS_WS_MESSAGE_SLOTS - (telemetry ? 2 : 0); ++i) if (!s_messages[i].refs) { ++ unsigned begin=kind==2 ? TS_WS_MESSAGE_SLOTS : kind==1 ? 0 : TS_WS_MESSAGE_SLOTS-2; ++ unsigned end=kind==2 ? TS_WS_ALL_MESSAGE_SLOTS : kind==1 ? TS_WS_MESSAGE_SLOTS-2 : TS_WS_MESSAGE_SLOTS; ++ for (unsigned i=begin; capacity <= TS_WS_TOTAL_BYTES-s_tx_stats.bytes && irefs = 1; m->capacity = capacity; + s_tx_stats.bytes += capacity; + if(s_tx_stats.bytes > s_tx_stats.bytes_high) s_tx_stats.bytes_high=s_tx_stats.bytes; +@@ -140,7 +143,12 @@ + portEXIT_CRITICAL(&s_lock); + if (m) { + m->text = malloc(capacity); +- if (!m->text) { ts_ws_message_release(m); return NULL; } ++ if (!m->text) { ++ portENTER_CRITICAL(&s_lock);s_tx_stats.rejected++;portEXIT_CRITICAL(&s_lock); ++ ts_ws_message_release(m);return NULL; ++ } ++ } else { ++ portENTER_CRITICAL(&s_lock);s_tx_stats.rejected++;portEXIT_CRITICAL(&s_lock); + } + return m; + } +@@ -260,12 +268,19 @@ + { + esp_err_t ret=httpd_queue_work(d->peer.server,deliver,d); + portENTER_CRITICAL(&s_lock); +- if(ret==ESP_OK)s_tx_stats.queued++; +- else {s_tx_stats.rejected++;s_server.work_busy=false;d->state=TX_CANCELED;} ++ bool retry=ret!=ESP_OK && d>=&s_deliveries[TS_WS_TX_SLOTS]; ++ if(ret==ESP_OK){s_tx_stats.queued++;s_server.retry_at=0;} ++ else { ++ s_tx_stats.rejected++;s_server.work_busy=false; ++ d->state=retry?TX_PREPARED:TX_CANCELED; ++ if(retry)s_server.retry_at=esp_timer_get_time()+100000; ++ } + portEXIT_CRITICAL(&s_lock); + if(ret!=ESP_OK){ +- if(d->done)d->done(d->revision,d->delivery,ret); +- delivery_release(d); /* work reference */ ++ if(!retry) { ++ if(d->done)d->done(d->revision,d->delivery,ret); ++ delivery_release(d); /* failed ordinary work reference */ ++ } + ts_ws_subscriptions_wake(); + } + delivery_release(d); /* publication reference, may outlive the callback */ +@@ -275,8 +290,8 @@ + { + delivery_t *next=NULL; + portENTER_CRITICAL(&s_lock); +- if(!s_server.stopping && !s_server.work_busy) { +- for(unsigned i=0;i=s_server.retry_at) { ++ for(unsigned i=0;iorder))next=&s_deliveries[i]; + if(next){next->state=TX_QUEUED;next->refs++;s_server.work_busy=true;} + } +@@ -287,17 +302,17 @@ + { + bool ready=false; + portENTER_CRITICAL(&s_lock); +- if(!s_server.stopping && !s_server.work_busy) +- for(unsigned i=0;istate==TX_PREPARED && (!topics_only || d->done); ++ bool cancel=d->state==TX_PREPARED && (!topics_only || istate=TX_CANCELED;s_tx_stats.stale++;} /* take its existing work reference */ + portEXIT_CRITICAL(&s_lock); + if(cancel){if(d->done)d->done(d->revision,d->delivery,ESP_ERR_INVALID_STATE);delivery_release(d);} +@@ -310,7 +325,7 @@ + if(!message)return ESP_ERR_INVALID_ARG; + delivery_t *d=NULL; + portENTER_CRITICAL(&s_lock); +- if(peer_valid(peer) && s_delivery_order!=UINT64_MAX) ++ if(!s_server.stopping && peer_valid(peer) && s_delivery_order!=UINT64_MAX) + for(unsigned i=done?0:TS_WS_TOPIC_TX_SLOTS;i<(done?TS_WS_TOPIC_TX_SLOTS:TS_WS_TX_SLOTS);i++)if(!s_deliveries[i].refs){ + d=&s_deliveries[i]; + *d=(delivery_t){.refs=2,.state=TX_PREPARED,.order=++s_delivery_order,.peer=peer, +@@ -355,7 +370,7 @@ + if (server != s_server.handle) { portEXIT_CRITICAL(&s_lock); return ESP_ERR_INVALID_ARG; } + s_server.stopping = true; + portEXIT_CRITICAL(&s_lock); +- cancel_ready(false); ++ ts_ws_transport_flush(); /* drain accepted results; never cancel them on normal stop */ + portENTER_CRITICAL(&s_lock); + unsigned outstanding=s_server.outstanding; + portEXIT_CRITICAL(&s_lock); +@@ -375,29 +390,30 @@ + portEXIT_CRITICAL(&s_lock); + } + +-static bool log_allowed(uint64_t connection, uint64_t level) ++static bool log_allowed(uint64_t revision, uint64_t level) + { + bool allowed=false; + portENTER_CRITICAL(&s_lock); + for(unsigned i=0;i=0 && level<=(unsigned)s_log_levels[i]) allowed=true; ++ if(s_peers[i].connection && s_log_revisions[i]==revision && s_log_levels[i]>=0 && level<=(unsigned)s_log_levels[i]) allowed=true; + portEXIT_CRITICAL(&s_lock); + return allowed; + } + static esp_err_t broadcast_filtered(const httpd_ws_frame_t *frame, int level) + { + ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ uint64_t revisions[TS_WS_CONNECTIONS]; + unsigned n=0; + portENTER_CRITICAL(&s_lock); + if(!s_server.stopping) for(unsigned i=0;ipayload,frame->len); + if(!m) return ESP_ERR_NO_MEM; + esp_err_t ret=ESP_OK; + for(unsigned i=0;iTS_WS_RESERVATION_TARGETS || !bytes || bytes>TS_WS_LEGACY_BYTES) return ESP_ERR_INVALID_ARG; ++ *r=(ts_ws_reservation_t){0}; ++ ts_ws_message_t *m=message_alloc(bytes,result?2:1); ++ if(!m) return ESP_ERR_NO_MEM; ++ unsigned begin=result?TS_WS_TX_SLOTS:0, end=result?TS_WS_ALL_TX_SLOTS:TS_WS_TOPIC_TX_SLOTS; ++ portENTER_CRITICAL(&s_lock); ++ bool valid=!s_server.stopping && s_server.handle; ++ for(unsigned i=0;peers && i=count) { ++ for(unsigned i=begin,j=0;islots[j++]=i;m->refs++;s_server.outstanding++;s_tx_stats.jobs++; ++ } ++ r->count=count;r->message=m; ++ if(s_tx_stats.jobs>s_tx_stats.jobs_high)s_tx_stats.jobs_high=s_tx_stats.jobs; ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if(!r->message){ts_ws_message_release(m);return valid?ESP_ERR_NO_MEM:ESP_ERR_INVALID_STATE;} ++ return ESP_OK; ++} ++void ts_ws_reservation_release(ts_ws_reservation_t *r) ++{ ++ if(!r || !r->message)return; ++ for(unsigned i=0;icount;i++)if(r->slots[i]>=0) delivery_release(&s_deliveries[r->slots[i]]); ++ ts_ws_message_release(r->message); ++ *r=(ts_ws_reservation_t){0}; ++ ts_ws_subscriptions_wake(); ++} ++bool ts_ws_reserved_json(ts_ws_reservation_t *r,const char *topic,const cJSON *data,int64_t timestamp) ++{ ++ if(!r->message)return false; ++ cJSON *root=cJSON_CreateObject(); ++ bool ok=root && cJSON_AddStringToObject(root,"type","data") && cJSON_AddStringToObject(root,"topic",topic) && ++ cJSON_AddNumberToObject(root,"timestamp",timestamp) && ts_ws_json_reference(root,"data",data) && ++ cJSON_PrintPreallocated(root,r->message->text,r->message->capacity,false); ++ cJSON_Delete(root); ++ if(ok)r->message->len=strlen(r->message->text); ++ return ok; ++} ++esp_err_t ts_ws_reserved_text(ts_ws_reservation_t *r,const char *text) ++{ ++ if(!r || !r->message || !text)return ESP_ERR_INVALID_ARG; ++ size_t n=strlen(text); ++ if(n>=r->message->capacity)return ESP_ERR_INVALID_SIZE; ++ memcpy(r->message->text,text,n+1);r->message->len=n; ++ return ESP_OK; ++} ++esp_err_t ts_ws_reserved_submit(ts_ws_reservation_t *r,unsigned index,uint64_t revision, ++ uint64_t delivery,ts_ws_delivery_check_t check,ts_ws_delivery_done_t done) ++{ ++ if(!r || !r->message || index>=r->count || r->slots[index]<0)return ESP_ERR_INVALID_ARG; ++ delivery_t *d=&s_deliveries[r->slots[index]]; ++ portENTER_CRITICAL(&s_lock); ++ bool valid=!s_server.stopping && peer_valid(d->peer) && s_delivery_order!=UINT64_MAX; ++ if(valid) { ++ d->revision=revision;d->delivery=delivery;d->check=check;d->done=done; ++ d->order=++s_delivery_order;d->state=TX_PREPARED;d->refs++; /* work + reservation */ ++ } ++ portEXIT_CRITICAL(&s_lock); ++ if(!valid)return ESP_ERR_INVALID_STATE; ++ r->slots[index]=-1; ++ ts_ws_transport_flush();delivery_release(d);ts_ws_subscriptions_wake(); ++ return ESP_OK; ++} ++ ++esp_err_t ts_ws_result_reserve(size_t bytes,ts_ws_reservation_t *r) ++{ ++ return ts_ws_reserve(NULL,TS_WS_CONNECTIONS,true,bytes,r); ++} ++esp_err_t ts_ws_result_broadcast(ts_ws_reservation_t *r,const char *text) ++{ ++ esp_err_t ret=ts_ws_reserved_text(r,text); ++ if(ret!=ESP_OK)return ret; ++ ts_ws_peer_t peers[TS_WS_CONNECTIONS]; ++ unsigned n=ts_ws_peer_snapshot(peers,TS_WS_CONNECTIONS); ++ for(unsigned i=0;i=r->count || r->slots[i]<0)return ESP_ERR_INVALID_STATE; ++ portENTER_CRITICAL(&s_lock);s_deliveries[r->slots[i]].peer=peers[i];portEXIT_CRITICAL(&s_lock); ++ esp_err_t result=ts_ws_reserved_submit(r,i,0,0,NULL,NULL); ++ if(result!=ESP_OK)ret=result; ++ } ++ return ret; ++} ++ ++uint32_t ts_ws_transport_retry_ms(void) ++{ ++ portENTER_CRITICAL(&s_lock); ++ int64_t delta=s_server.retry_at-esp_timer_get_time(); ++ portEXIT_CRITICAL(&s_lock); ++ return delta>0 ? (uint32_t)((delta+999)/1000) : 0; ++} +--- a/main/ts_core_init.c ++++ b/main/ts_core_init.c +@@ -21,6 +21,26 @@ + + static bool s_core_initialized = false; + static bool s_core_started = false; ++static bool s_core_cleanup_pending; ++static bool s_core_stopping; ++ ++static esp_err_t core_release_components(void) ++{ ++ esp_err_t ret; ++ if (ts_service_is_initialized() && (ret = ts_service_deinit()) != ESP_OK) return ret; ++ if (ts_event_is_initialized() && (ret = ts_event_deinit()) != ESP_OK) return ret; ++ if (ts_log_is_initialized() && (ret = ts_log_deinit()) != ESP_OK) return ret; ++ if (ts_config_is_initialized() && (ret = ts_config_deinit()) != ESP_OK) return ret; ++ return ESP_OK; ++} ++static esp_err_t core_init_rollback(esp_err_t original) ++{ ++ s_core_cleanup_pending=true; ++ esp_err_t ret=core_release_components(); ++ if(ret!=ESP_OK)return ret; ++ s_core_cleanup_pending=false; ++ return original; ++} + + /* ============================================================================ + * cJSON PSRAM 内存钩子 - 减少 DRAM 碎片 +@@ -61,7 +81,7 @@ + { + esp_err_t ret; + +- if (s_core_initialized) { ++ if (s_core_initialized || s_core_cleanup_pending) { + ESP_LOGW(TAG, "Core already initialized"); + return ESP_ERR_INVALID_STATE; + } +@@ -112,8 +132,7 @@ + ret = ts_log_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize log: %s", esp_err_to_name(ret)); +- ts_config_deinit(); +- return ret; ++ return core_init_rollback(ret); + } + + // 3. 初始化事件系统 +@@ -121,9 +140,7 @@ + ret = ts_event_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize event: %s", esp_err_to_name(ret)); +- ts_log_deinit(); +- ts_config_deinit(); +- return ret; ++ return core_init_rollback(ret); + } + + // 3.1 注册 config_file 事件监听器(依赖事件系统) +@@ -145,10 +162,7 @@ + ret = ts_service_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize service: %s", esp_err_to_name(ret)); +- ts_event_deinit(); +- ts_log_deinit(); +- ts_config_deinit(); +- return ret; ++ return core_init_rollback(ret); + } + + s_core_initialized = true; +@@ -159,26 +173,15 @@ + + esp_err_t ts_core_deinit(void) + { +- if (!s_core_initialized) { +- return ESP_ERR_INVALID_STATE; +- } +- +- ESP_LOGI(TAG, "Deinitializing TianShanOS Core..."); +- +- // 如果已启动,先停止 +- if (s_core_started) { +- ts_core_stop(); +- } +- +- // 按相反顺序反初始化 +- ts_service_deinit(); +- ts_event_deinit(); +- ts_log_deinit(); +- ts_config_deinit(); +- +- s_core_initialized = false; +- ESP_LOGI(TAG, "TianShanOS Core deinitialized"); +- ++ if (!s_core_initialized && !s_core_cleanup_pending) return ESP_ERR_INVALID_STATE; ++ s_core_cleanup_pending=true; ++ esp_err_t ret = ts_core_stop(); ++ if (ret != ESP_OK) return ret; ++ /* Earlier stages may already have completed on a previous attempt. */ ++ ret=core_release_components(); ++ if(ret!=ESP_OK)return ret; ++ s_core_initialized=false; ++ s_core_cleanup_pending=false; + return ESP_OK; + } + +@@ -189,6 +192,7 @@ + + esp_err_t ts_core_start(void) + { ++ if(s_core_stopping || s_core_cleanup_pending) return ESP_ERR_INVALID_STATE; + if (!s_core_initialized) { + ESP_LOGE(TAG, "Core not initialized"); + return ESP_ERR_INVALID_STATE; +@@ -232,17 +236,24 @@ + } + + ESP_LOGI(TAG, "Stopping TianShanOS..."); +- +- // 发送系统关闭事件 +- ts_event_post_sync(TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_SHUTDOWN, NULL, 0); ++ esp_err_t ret; ++ /* A retry continues the same stop intent; do not replay shutdown handlers. */ ++ if(!s_core_stopping) { ++ s_core_stopping=true; ++ ret=ts_event_post_sync(TS_EVENT_BASE_SYSTEM,TS_EVENT_SYSTEM_SHUTDOWN,NULL,0); ++ if(ret!=ESP_OK){s_core_stopping=false;return ret;} ++ } + + // 停止所有服务 +- ts_service_stop_all(); ++ ret = ts_service_stop_all(); ++ if (ret != ESP_OK) return ret; + + // 保存配置 +- ts_config_save(); ++ ret = ts_config_save(); ++ if (ret != ESP_OK) return ret; + + s_core_started = false; ++ s_core_stopping=false; + ESP_LOGI(TAG, "TianShanOS stopped"); + + return ESP_OK; +--- a/tests/ws_subscriptions/README.md ++++ b/tests/ws_subscriptions/README.md +@@ -17,3 +17,10 @@ + - The 32-service escaped-name payload is a size stress fixture for the production serializer, not a replacement implementation of the service API. The 512 KiB legacy-frame boundary and total bytes / descriptor ceilings are tested separately. + + Mock success of `httpd_ws_send_frame_async` means only success at that API boundary. It is not proof of browser delivery, TCP timing, device heap, CPU utilization, or stack high-water on ESP32-S3. See `docs/repair/ws-subscriptions/README.md` for the acceptance matrix and device checklist. ++ ++ ++## R1—R5 Reviewer 修复回归 ++ ++- `bash tests/ws_subscriptions/run_reviewer_baseline.sh`:使用归档和 SHA-256 复现五项未修复行为,退出 0 表示反例成立。 ++- `bash tests/ws_subscriptions/run_reviewer.sh`:完整生产 manager/transport/event C + 自动提取的当前 WebUI/HTTP/服务/核心函数,验证暂停/排空、会话就绪、日志代次、聚合停止重试、主题公平性和联合资源预算。SSH/设备/SDK 是模拟,未执行远端操作。 ++- 修复记录:`docs/repair/ws-subscriptions/reviewer-fixes/README.md`。 +--- /dev/null ++++ b/tests/ws_subscriptions/run_reviewer.sh +@@ -0,0 +1,37 @@ ++#!/bin/bash ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++build=$(mktemp -d /tmp/ts-ws-reviewer.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++export DEVELOPER_DIR=/Library/Developer/CommandLineTools ++cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" ++python3 - "$build" <<'PY' ++from pathlib import Path ++import sys,re ++s=Path('components/ts_webui/src/ts_webui_ws.c').read_text() ++names=['ts_webui_log_stream_enable','has_log_clients','update_log_stream_state','set_client_role','ssh_terminal_done','ssh_generation_valid','ssh_status_valid','ssh_request_error','ssh_send_status','ssh_send_output','ssh_poll_task','ssh_cleanup','handle_ssh_connect','start_terminal_session','ts_webui_ws_stop','ssh_exec_terminal_publish','ws_handler'] ++parts=[] ++for name in names: ++ m=re.search(r'^(?:static )?(?:esp_err_t|bool|void) '+name+r'\([^;]*?\)\n\{',s,re.M);assert m,name ++ parts.append(s[m.start():s.index('\n}',m.start())+2]) ++Path(sys.argv[1],'reviewer_ws.inc').write_text('\n'.join(parts)) ++for source,names,dest in [ ++ ('components/ts_net/src/ts_http_server.c',['http_handler_wrapper'],'reviewer_http.inc'), ++ ('main/ts_core_init.c',['core_release_components','core_init_rollback','ts_core_start','ts_core_stop','ts_core_deinit'],'reviewer_core.inc'), ++ ('components/ts_core/ts_service/src/ts_service.c',['stop_service_internal','ts_service_stop','ts_service_stop_all','ts_service_deinit'],'reviewer_service.inc')]: ++ s=Path(source).read_text();parts=[] ++ for name in names: ++ m=re.search(r'^(?:static )?esp_err_t '+name+r'\([^;]*?\)\n\{',s,re.M);assert m,name ++ parts.append(s[m.start():s.index('\n}',m.start())+2]) ++ Path(sys.argv[1],dest).write_text('\n'.join(parts)) ++PY ++cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer.c "$cjson/cJSON.c" -o "$build/reviewer" ++"$build/reviewer" ++ ++cc -std=gnu11 -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer_service.c -o "$build/service" ++"$build/service" ++cc -std=gnu11 -g -fsanitize=address,undefined -Wno-deprecated-declarations -Icomponents/ts_core/ts_event/include -Itests/ws_subscriptions/stubs -Icomponents/ts_core/ts_event/src -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer_core.c -o "$build/core" ++"$build/core" ++ ++cc -std=gnu11 -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -I"$cjson" -I"$build" tests/ws_subscriptions/test_reviewer_http.c -o "$build/http" ++"$build/http" +--- /dev/null ++++ b/tests/ws_subscriptions/run_reviewer_baseline.sh +@@ -0,0 +1,27 @@ ++#!/bin/bash ++# Reproduce the five defects against the frozen uncommitted pre-fix source, not HEAD. ++set -euo pipefail ++cd "$(dirname "$0")/../.." ++root=$PWD ++fixture=docs/repair/ws-subscriptions/reviewer-fixes ++build=$(mktemp -d /tmp/ts-ws-pre-fix.XXXXXX) ++trap 'rm -rf "$build"' EXIT ++tar -xzf "$fixture/pre-fix-source.tar.gz" -C "$build" ++python3 - "$build" "$fixture" <<'PY' ++from pathlib import Path ++import json,hashlib,sys ++base=Path(sys.argv[1]);fixture=Path(sys.argv[2]) ++for name,digest in json.loads((fixture/'baseline.json').read_text())['sha256'].items(): ++ assert hashlib.sha256((base/name).read_bytes()).hexdigest()==digest,name ++for origin,dest in [('ts-review-ws/review.c','r1_r3.c'),('ts-review-ws-round2/starvation.c','r5.c'),('ts-review-ws-round2/core_stop.c','r4_core.c'),('ts-review-ws-round2/service_stop.c','r4_service.c')]: ++ s=(fixture/origin).read_text().replace('/Users/massif/TianshanOS/tests/ws_subscriptions/test_manager.c','test_manager.c') ++ (base/dest).write_text(s) ++PY ++export DEVELOPER_DIR=/Library/Developer/CommandLineTools ++cjson="${IDF_PATH:-/Users/massif/esp/v5.5.2/esp-idf}/components/json/cJSON" ++for case in r1_r3 r5 r4_core r4_service; do ++ extra=() ++ if [[ "$case" == r4_core ]]; then extra=(-I"$build/components/ts_core/ts_event/include"); fi ++ cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined "${extra[@]}" -I"$build/tests/ws_subscriptions" -I"$build/tests/ws_subscriptions/stubs" -I"$build/components/ts_webui/include" -I"$build/components/ts_webui/src" -I"$build/components/ts_core/ts_event/include" -I"$build/components/ts_core/ts_event/src" -I"$cjson" "$build/$case.c" "$cjson/cJSON.c" -o "$build/$case" ++ "$build/$case" ++done +--- a/tests/ws_subscriptions/stubs/platform.h ++++ b/tests/ws_subscriptions/stubs/platform.h +@@ -93,7 +93,7 @@ + static inline int ts_event_unregister_sync(void*h,unsigned t) {(void)h;(void)t;return 0;} + #endif + typedef void *httpd_handle_t; +-typedef struct {httpd_handle_t handle;void*sess_ctx;void(*free_ctx)(void*);int fd;} httpd_req_t; ++typedef struct {httpd_handle_t handle;void*sess_ctx;void(*free_ctx)(void*);int fd;int method;void*user_ctx;const char*uri;size_t content_len;} httpd_req_t; + typedef struct {int type;uint8_t*payload;size_t len;} httpd_ws_frame_t; + #define HTTPD_WS_TYPE_TEXT 1 + #define HTTPD_WS_CLIENT_WEBSOCKET 2 +--- a/tests/ws_subscriptions/test_init.c ++++ b/tests/ws_subscriptions/test_init.c +@@ -25,6 +25,12 @@ + static atomic_uint s_exec_creators; + bool ts_ws_transport_in_context(void){return owner_context;} + static esp_err_t ts_ws_subscriptions_deinit(void){return manager_stop_result;} ++static esp_err_t ts_ws_subscriptions_pause(void){return manager_stop_result;} ++static esp_err_t ts_ws_subscriptions_drain(void){return manager_stop_result;} ++static esp_err_t ts_webui_log_stream_enable(bool enable){(void)enable;return ESP_OK;} ++static ts_ws_reservation_t s_exec_terminal; ++esp_err_t ts_ws_result_reserve(size_t bytes,ts_ws_reservation_t*r){(void)bytes;(void)r;return 0;} ++void ts_ws_reservation_release(ts_ws_reservation_t*r){(void)r;} + esp_err_t ts_ws_transport_quiesce(httpd_handle_t server,uint32_t timeout){(void)server;(void)timeout;return barrier_result;} + esp_err_t ts_ws_transport_stop(httpd_handle_t server,uint32_t timeout){(void)server;(void)timeout;tx_stop_calls++;return tx_stop_result;} + static void ssh_cleanup(void){if(cleanup_finishes)s_ssh_poll_alive=false;} +--- a/tests/ws_subscriptions/test_manager.c ++++ b/tests/ws_subscriptions/test_manager.c +@@ -41,6 +41,7 @@ + static void(*barrier_action)(void); + static void test_point(const char *name) {if(barrier_action && !strcmp(name,barrier_name)){void(*fn)(void)=barrier_action;barrier_action=NULL;fn();}} + static unsigned reads[7], frames[32], notifications, queued; ++static void (*sent_hook)(httpd_ws_frame_t*); + static char payloads[64][TS_WS_FRAME_BYTES]; + static struct {void(*fn)(void*);void*arg;} queue[64]; + TaskHandle_t xTaskGetCurrentTaskHandle(void) {return current;} +@@ -50,7 +51,7 @@ + void vTaskDelete(TaskHandle_t t) {(void)t;} + void vTaskDelay(TickType_t t) {test_now+=(int64_t)t*1000;if(delay_hook)delay_hook();} + int httpd_ws_get_fd_info(httpd_handle_t h,int fd) {(void)h;(void)fd;return HTTPD_WS_CLIENT_WEBSOCKET;} +-int httpd_ws_send_frame_async(httpd_handle_t h,int fd,httpd_ws_frame_t*f) {(void)h;assert(fd>=0&&fd<32);frames[fd]++;memcpy(payloads[fd],f->payload,f->len);payloads[fd][f->len]=0;return send_fail?ESP_FAIL:0;} ++int httpd_ws_send_frame_async(httpd_handle_t h,int fd,httpd_ws_frame_t*f) {(void)h;assert(fd>=0&&fd<32);frames[fd]++;if(sent_hook && !send_fail)sent_hook(f);memcpy(payloads[fd],f->payload,f->len);payloads[fd][f->len]=0;return send_fail?ESP_FAIL:0;} + int httpd_queue_work(httpd_handle_t h,void(*fn)(void*),void*a) {(void)h;if(queue_fail)return ESP_FAIL;if(immediate) {TaskHandle_t saved=current;current=(void*)3;fn(a);current=saved;}else{assert(queued<64);queue[queued++]=(typeof(queue[0])){fn,a};}return 0;} + int ts_api_call(const char*method,const cJSON*p,ts_api_result_t*r) {(void)p;for(int i=0;i<7;i++)if(!strcmp(metrics[i],method))reads[i]++;if(api_hook)api_hook();r->data=cJSON_CreateObject();r->message=malloc(8);r->code=api_business_error?1:0;return 0;} + static void pump(void) { +--- /dev/null ++++ b/tests/ws_subscriptions/test_reviewer.c +@@ -0,0 +1,219 @@ ++/* Compose actual manager/transport with extracted, unmodified WebUI functions. */ ++#define main existing_manager_main ++#include "test_manager.c" ++#undef main ++#include ++#include ++#define MAX_WS_CLIENTS TS_WS_CONNECTIONS ++#define TS_LOG_NONE 0 ++#define TS_LOG_ERROR 1 ++#define TS_LOG_VERBOSE 5 ++#define HTTP_GET 0 ++#define HTTPD_WS_TYPE_CLOSE 8 ++#define CONFIG_TS_LOG_BUFFER_SIZE 16 ++#define SSH_OUTPUT_BUF_SIZE 4096 ++#define TS_SSH_AUTH_PASSWORD 1 ++typedef int ts_log_level_t; ++typedef enum {WS_CLIENT_TYPE_EVENT,WS_CLIENT_TYPE_TERMINAL,WS_CLIENT_TYPE_SSH_SHELL,WS_CLIENT_TYPE_LOG} ws_client_type_t; ++static struct {bool active;int fd;httpd_handle_t hd;ws_client_type_t type;int log_min_level;}s_clients[MAX_WS_CLIENTS]; ++static httpd_handle_t s_server=(void*)11; ++static bool s_ws_stopping,s_exec_running; ++static atomic_uint s_exec_creators; ++static ts_event_handler_handle_t s_power_event_handle; ++static ts_ws_peer_t s_ssh_peer; ++static int s_ssh_client_fd=-1,s_terminal_client_fd=-1; ++static void *s_ssh_session,*s_ssh_shell; ++static atomic_bool s_ssh_running,s_ssh_poll_alive; ++enum {SSH_IDLE,SSH_STARTING,SSH_READY,SSH_TERMINAL}; ++static atomic_uint s_ssh_state,s_ssh_generation,s_ssh_result_pending; ++static ts_ws_reservation_t s_ssh_terminal,s_exec_terminal; ++static bool shell_active,create_fails,close_on_create; ++static void update_log_stream_state(void); ++static bool has_log_clients(void); ++static int ts_webui_log_stream_enable(bool enabled); ++static void*s_log_callback_handle; ++static atomic_bool s_log_streaming_enabled; ++static int remove_log_result; ++static const char *incoming; ++static unsigned commands; ++static const char*s_level_names[]={"NONE","ERROR","WARN","INFO","DEBUG","VERBOSE"}; ++typedef struct{int timestamp_ms,level;const char*tag,*message,*task_name;}ts_log_entry_t; ++static void log_ws_callback(const ts_log_entry_t*e,void*u){(void)e;(void)u;} ++static int ts_log_add_callback(void(*fn)(const ts_log_entry_t*,void*),int level,void*u,void**h){(void)fn;(void)level;(void)u;*h=(void*)1;return 0;} ++static int ts_log_remove_callback(void*h){(void)h;return remove_log_result;} ++static size_t ts_log_buffer_search(ts_log_entry_t*e,size_t n,int a,int b,void*t,void*m){(void)e;(void)n;(void)a;(void)b;(void)t;(void)m;return 0;} ++static void*test_heap_malloc(size_t n,unsigned caps){(void)caps;return tracked_malloc(n);} ++static int add_client(httpd_req_t*r,ws_client_type_t t){(void)r;(void)t;commands++;return 0;} ++static int httpd_ws_recv_frame(httpd_req_t*r,httpd_ws_frame_t*f,size_t n){(void)r;f->type=HTTPD_WS_TYPE_TEXT;f->len=strlen(incoming);if(n)memcpy(f->payload,incoming,f->len);return 0;} ++static void handle_terminal_command(httpd_req_t*r,const char*d){(void)r;(void)d;commands++;} ++static void ts_console_request_interrupt(void){commands++;} ++static void handle_ssh_input(const char*d){(void)d;commands++;} ++static void handle_ssh_disconnect(void){commands++;} ++static void handle_ssh_signal(const char*s){(void)s;commands++;} ++static void handle_ssh_resize(int w,int h){(void)w;(void)h;commands++;} ++static int httpd_ws_send_frame(httpd_req_t*r,httpd_ws_frame_t*f){return httpd_ws_send_frame_async(r->handle,r->fd,f);} ++static void ts_console_clear_output_cb(void){} ++static void terminal_output_cb(const char*d,size_t n,void*u){(void)d;(void)n;(void)u;} ++static void ts_console_set_output_cb(void(*fn)(const char*,size_t,void*),void*u){(void)fn;(void)u;} ++static void cleanup_disconnected_client(int fd){(void)fd;} ++static void ssh_cleanup(void); ++static esp_err_t ssh_send_status(const char*,const char*); ++static void ssh_send_output(const char*d,size_t n); ++typedef struct {const char*host,*username;int port,auth_method,timeout_ms;struct {const char*password;}auth;}ts_ssh_config_t; ++typedef struct {int term_width,term_height,read_timeout_ms;}ts_shell_config_t; ++#define TS_SSH_DEFAULT_CONFIG() ((ts_ssh_config_t){0}) ++#define TS_SHELL_DEFAULT_CONFIG() ((ts_shell_config_t){0}) ++static int ts_ssh_session_create(const ts_ssh_config_t*c,void**out){(void)c;*out=(void*)5;return 0;} ++static int ts_ssh_connect(void*s){(void)s;return 0;} ++static const char*ts_ssh_get_error(void*s){(void)s;return "fixture";} ++static int ts_ssh_shell_open(void*s,const ts_shell_config_t*c,void**out){(void)s;(void)c;*out=(void*)6;shell_active=true;return 0;} ++static bool ts_ssh_shell_is_active(void*s){return s && shell_active;} ++static int ts_ssh_shell_read(void*s,char*b,size_t n,size_t*out){(void)s;(void)b;(void)n;*out=0;return 0;} ++static void ts_ssh_shell_close(void*s){(void)s;shell_active=false;} ++static void ts_ssh_disconnect(void*s){(void)s;} ++static void ts_ssh_session_destroy(void*s){(void)s;} ++static int xTaskCreateWithCaps(void(*fn)(void*),const char*n,unsigned size,void*a,unsigned prio,void*out,unsigned caps){ ++ (void)fn;(void)n;(void)size;(void)a;(void)prio;(void)out;(void)caps; ++ if(close_on_create)shell_active=false; ++ return create_fails?0:pdPASS; ++} ++#define free tracked_free ++#define malloc tracked_malloc ++#define heap_caps_malloc test_heap_malloc ++#include "reviewer_ws.inc" ++#undef free ++#undef malloc ++#undef heap_caps_malloc ++static jmp_buf worker_yield; ++static void yield_worker(void){longjmp(worker_yield,1);} ++static void worker_step(void){ ++ wait_hook=yield_worker;current=(void*)2; ++ if(!setjmp(worker_yield))worker_fn(NULL); ++ current=(void*)1;wait_hook=NULL; ++} ++static void sdk_one(void){ ++ if(!queued)return; ++ current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(queue[0]));q.fn(q.arg);current=(void*)1; ++} ++static void progress(void){sdk_one();if(s_worker){if(s_state==STOPPING)worker_exit();else worker_step();}} ++static void poll_exit(void){current=(void*)4;ssh_poll_task(NULL);current=(void*)3;} ++static void finish(void){ ++ s_exec_running=false;delay_hook=progress;assert(ts_webui_ws_stop((void*)11)==ESP_OK);delay_hook=NULL; ++ for(int i=0;i<32;i++)if(reqs[i].sess_ctx)close_peer(i); ++ ts_ws_transport_stopped((void*)11);assert(!live_allocations); ++ s_ws_stopping=false; ++} ++static void connect_request(bool fail,bool close_early){ ++ create_fails=fail;close_on_create=close_early; ++ cJSON*params=cJSON_Parse("{\"host\":\"fixture\",\"user\":\"fixture\"}"); ++ current=(void*)3;delay_hook=poll_exit;handle_ssh_connect(&reqs[1],params);delay_hook=NULL;current=(void*)1;cJSON_Delete(params); ++} ++static unsigned observed_topics[8]; ++static void observe_topic(httpd_ws_frame_t*f){ ++ for(unsigned i=0;i<8;i++){ ++ char match[80];snprintf(match,sizeof(match),"\"topic\":\"%s\"",topics[i].name); ++ if(strstr((const char*)f->payload,match))observed_topics[i]++; ++ } ++} ++int main(void){ ++ cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); ++ start();open_peer(1);open_peer(2);assert(ts_ws_result_reserve(4096,&s_exec_terminal)==0);s_exec_running=true;delay_hook=progress; ++ assert(ts_webui_ws_stop((void*)11)==ESP_ERR_INVALID_STATE);delay_hook=NULL; ++ assert(s_worker && s_state==DRAINING); ++ reqs[1].method=1;incoming="{\"type\":\"ping\"}";current=(void*)3; ++ assert(ws_handler(&reqs[1])==0 && strstr(payloads[1],"pong")); ++ incoming="{\"type\":\"terminal_input\",\"data\":\"new-command\"}"; ++ assert(ws_handler(&reqs[1])==0 && !commands && strstr(payloads[1],"stopping"));current=(void*)1; ++ unsigned a=frames[1],b=frames[2]; ++ httpd_ws_frame_t result={.payload=(uint8_t*)"final-result",.len=12}; ++ ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\",\"session_id\":1}",1); ++ sdk_one();assert(!queued && ts_ws_transport_needs_flush()); ++ worker_step();sdk_one();assert(frames[1]==a+1 && frames[2]==b+1); ++ assert(!transport_server.outstanding);finish(); ++ puts("PASS R1: busy stop retains real worker; final fanout drains with no new producer message"); ++ start();open_peer(1);open_peer(2); ++ assert(ts_webui_ws_stop((void*)11)==ESP_ERR_TIMEOUT && s_worker && s_state==DRAINING); ++ a=frames[1];b=frames[2];assert(ts_ws_transport_broadcast(&result)==0); ++ for(unsigned i=0;i<4;i++){sdk_one();worker_step();} ++ assert(frames[1]==a+1 && frames[2]==b+1);finish(); ++ start();open_peer(1);open_peer(2);a=frames[1];b=frames[2]; ++ assert(ts_ws_transport_broadcast(&result)==0);assert(ts_ws_subscriptions_pause()==0); ++ assert(ts_ws_transport_stop((void*)11,1)==ESP_ERR_TIMEOUT && s_worker); ++ sdk_one();worker_step();sdk_one();assert(frames[1]==a+1 && frames[2]==b+1);finish(); ++ puts("PASS R1 timeout: handler-barrier and transport-drain failures retain worker; accepted fanout progresses before retry"); ++ ++ ++ start();ts_ws_peer_t peer=open_peer(1); ++ s_clients[0].active=true;s_clients[0].fd=1;s_clients[0].hd=peer.server; ++ set_client_role(peer,WS_CLIENT_TYPE_LOG,5); ++ httpd_ws_frame_t log={.payload=(uint8_t*)"old-log",.len=7}; ++ a=frames[1];assert(ts_ws_transport_log(&log,3)==0); ++ current=(void*)3;start_terminal_session(&reqs[1]);current=(void*)1; ++ assert(s_clients[0].type==WS_CLIENT_TYPE_TERMINAL);pump();assert(frames[1]==a+1); /* welcome only */ ++ set_client_role(peer,WS_CLIENT_TYPE_LOG,5); ++ assert(ts_ws_transport_log(&log,3)==0);set_client_role(peer,WS_CLIENT_TYPE_EVENT,0);set_client_role(peer,WS_CLIENT_TYPE_LOG,5); ++ a=frames[1];pump();assert(frames[1]==a); /* old generation cannot revive */ ++ assert(ts_ws_transport_log(&log,3)==0);pump();assert(frames[1]==a+1); ++ finish();s_terminal_client_fd=-1; ++ assert(ts_webui_log_stream_enable(true)==0);remove_log_result=ESP_ERR_INVALID_STATE; ++ assert(ts_webui_log_stream_enable(false)==ESP_ERR_INVALID_STATE && s_log_callback_handle && !s_log_streaming_enabled); ++ assert(ts_webui_log_stream_enable(true)==0 && s_log_streaming_enabled);remove_log_result=0;assert(ts_webui_log_stream_enable(false)==0); ++ puts("PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA"); ++ ++ start();peer=open_peer(1);s_clients[0].active=true;s_clients[0].fd=1;s_clients[0].hd=peer.server; ++ /* Occupy both ordinary buffers; a rejected startup still has its result slot. */ ++ ts_ws_message_t*m1=ts_ws_message_text("one",3),*m2=ts_ws_message_text("two",3);assert(m1&&m2); ++ set_client_role(peer,WS_CLIENT_TYPE_LOG,5); ++ connect_request(true,false);assert(s_clients[0].type!=WS_CLIENT_TYPE_LOG);assert(s_ssh_state==SSH_TERMINAL && !s_ssh_poll_alive && !s_ssh_session); ++ unsigned generation=s_ssh_generation; ++ connect_request(false,false);assert(s_ssh_generation==generation && strstr(payloads[1],"still pending")); ++ ts_ws_message_release(m1);ts_ws_message_release(m2);pump();assert(strstr(payloads[1],"Failed to create SSH session")); ++ connect_request(false,true);pump();assert(strstr(payloads[1],"closed during startup"));assert(!s_ssh_session); ++ connect_request(false,false);assert(s_ssh_state==SSH_READY && strstr(payloads[1],"connected")); ++ /* Queue a READY from a background caller, then close before it executes. */ ++ assert(ssh_send_status("connected","late readiness")==0); ++ unsigned old_generation=s_ssh_generation; ++ queue_fail=true;assert(ssh_send_status("error","fixture failure")==0); ++ sdk_one();worker_step();assert(!queued && ts_ws_transport_needs_flush());queue_fail=false; ++ assert(!ssh_status_valid(old_generation,SSH_READY)); ++ test_now+=100000;worker_step();pump();assert(strstr(payloads[1],"fixture failure")); ++ current=(void*)3;delay_hook=poll_exit;ssh_cleanup();delay_hook=NULL;current=(void*)1; ++ connect_request(false,false); ++ ts_ws_message_t *full1=ts_ws_message_text("full1",5),*full2=ts_ws_message_text("full2",5);assert(full1&&full2); ++ ssh_send_output("payload",7);assert(s_ssh_state==SSH_TERMINAL && !s_ssh_running); ++ poll_exit();current=(void*)1;ts_ws_message_release(full1);ts_ws_message_release(full2);pump(); ++ assert(strstr(payloads[1],"SSH output delivery failed") && !s_ssh_session && !s_ssh_poll_alive); ++ finish(); ++ puts("PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid"); ++ ++ start();open_peer(1);assert(ts_ws_result_reserve(TS_WS_LEGACY_BYTES,&s_exec_terminal)==0); ++ m1=ts_ws_message_text("one",3);m2=ts_ws_message_text("two",3);assert(m1&&m2); ++ open_peer(2);a=frames[1];b=frames[2]; ++ ssh_exec_terminal_publish("{\"type\":\"ssh_exec_done\",\"session_id\":7}",7); ++ ts_ws_message_release(m1);ts_ws_message_release(m2);pump();assert(frames[1]==a+1&&frames[2]==b+1);finish(); ++ puts("PASS R2 exec: admitted result reservation survives ordinary saturation and preserves recipients at completion"); ++ ++ start();peer=open_peer(1);uint64_t serial[8];for(unsigned i=0;i<8;i++){serial[i]=s_stats.serialized[i];subscribe(peer,topics[i].name,10000);} ++ sent_hook=observe_topic; ++ for(unsigned cycle=0;cycle<100;cycle++) {test_now+=10000000;run_batch();pump();} ++ for(unsigned i=0;i<8;i++) { ++ assert(observed_topics[i]>50 && observed_topics[i]==s_stats.serialized[i]-serial[i]); ++ printf("R5 observed %s: %u delivered frames\n",topics[i].name,observed_topics[i]); ++ } ++ /* Freeing capacity services still-due targets without waiting their next interval. */ ++ for(unsigned i=0;i<8;i++)serial[i]=s_stats.serialized[i]; ++ unsigned improved=0;run_batch();pump();for(unsigned i=0;i<8;i++)improved+=s_stats.serialized[i]>serial[i];assert(improved>=2); ++ ts_ws_message_t*held[6];cJSON*j=cJSON_CreateObject();for(unsigned i=0;i<6;i++){held[i]=ts_ws_message_json("held",j,0);assert(held[i]);} ++ test_now+=10000000;unsigned before=total_reads();run_batch();assert(total_reads()==before); ++ for(unsigned i=0;i<6;i++)ts_ws_message_release(held[i]);cJSON_Delete(j); ++ run_batch();pump();assert(total_reads()>before); ++ ts_ws_peer_t pinned[TS_WS_TOPIC_TX_SLOTS];for(unsigned i=0;ibefore); ++ char*large=malloc(TS_WS_LEGACY_BYTES);memset(large,'x',TS_WS_LEGACY_BYTES); ++ m1=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);m2=ts_ws_message_text(large,TS_WS_LEGACY_BYTES-1);assert(m1&&m2);free(large); ++ test_now+=10000000;before=total_reads();run_batch();assert(total_reads()==before); ++ ts_ws_message_release(m1);ts_ws_message_release(m2);run_batch();pump();assert(total_reads()>before);finish(); ++ puts("PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity"); ++} +--- /dev/null ++++ b/tests/ws_subscriptions/test_reviewer_core.c +@@ -0,0 +1,51 @@ ++#define TEST_REAL_EVENT ++#include "platform.h" ++#include ++#include "ts_event.c" ++int64_t test_now; ++TaskHandle_t xTaskGetCurrentTaskHandle(void){return (void*)pthread_self();} ++int xTaskCreate(void(*fn)(void*),const char*n,unsigned s,void*a,unsigned p,TaskHandle_t*out){(void)fn;(void)n;(void)s;(void)a;(void)p;*out=(void*)1;return pdPASS;} ++void vTaskDelete(TaskHandle_t t){(void)t;} ++void vTaskDelay(TickType_t t){test_now+=(int64_t)t*1000;} ++static pthread_mutex_t barrier=PTHREAD_MUTEX_INITIALIZER; ++static pthread_cond_t cv=PTHREAD_COND_INITIALIZER; ++static bool entered,release_callback; ++static void blocked(const ts_event_t*e,void*u){(void)e;(void)u;pthread_mutex_lock(&barrier);entered=true;pthread_cond_broadcast(&cv);while(!release_callback)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier);} ++static void*post(void*p){(void)p;ts_event_post_sync("test",1,NULL,0);return NULL;} ++ ++static bool s_core_cleanup_pending,s_core_stopping; ++static int ts_service_start_all(void){return 0;} ++static bool s_core_initialized=true,s_core_started=true,service_live=true,log_live=true,config_live=true; ++static int service_stop_result,save_result,log_result,config_result; ++static unsigned save_calls; ++static bool ts_service_is_initialized(void){return service_live;} ++static bool ts_log_is_initialized(void){return log_live;} ++static bool ts_config_is_initialized(void){return config_live;} ++static int ts_service_stop_all(void){return service_stop_result;} ++static int ts_config_save(void){save_calls++;return save_result;} ++static int ts_service_deinit(void){service_live=false;return 0;} ++static int ts_log_deinit(void){if(!log_result)log_live=false;return log_result;} ++static int ts_config_deinit(void){if(!config_result)config_live=false;return config_result;} ++#include "reviewer_core.inc" ++static unsigned shutdown_calls; ++static void shutdown_event(const ts_event_t*e,void*u){(void)e;(void)u;shutdown_calls++;} ++int main(void){ ++ s_event_ctx.initialized=true;s_event_ctx.running=true;s_event_ctx.mutex=xSemaphoreCreateMutex();s_event_ctx.event_queue=xQueueCreate(4,1); ++ ts_event_handler_handle_t shutdown_handle;assert(ts_event_register(TS_EVENT_BASE_SYSTEM,TS_EVENT_SYSTEM_SHUTDOWN,shutdown_event,NULL,&shutdown_handle)==0); ++ service_stop_result=ESP_ERR_TIMEOUT;assert(ts_core_stop()==ESP_ERR_TIMEOUT && s_core_started && save_calls==0); ++ assert(ts_core_start()==ESP_ERR_INVALID_STATE); ++ service_stop_result=0;save_result=ESP_FAIL;assert(ts_core_stop()==ESP_FAIL && s_core_started); ++ save_result=0;assert(ts_core_stop()==0 && !s_core_started && shutdown_calls==1); ++ ts_event_handler_handle_t h;assert(ts_event_register("test",1,blocked,NULL,&h)==0); ++ pthread_t thread;pthread_create(&thread,NULL,post,NULL); ++ pthread_mutex_lock(&barrier);while(!entered)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier); ++ assert(ts_core_deinit()==ESP_ERR_TIMEOUT && s_core_initialized && log_live && config_live && s_event_ctx.initialized && s_dispatch_scopes); ++ pthread_mutex_lock(&barrier);release_callback=true;pthread_cond_broadcast(&cv);pthread_mutex_unlock(&barrier);pthread_join(thread,NULL); ++ log_result=ESP_FAIL;assert(ts_core_deinit()==ESP_FAIL && s_core_initialized && config_live && !s_event_ctx.initialized); ++ log_result=0;config_result=ESP_FAIL;assert(ts_core_deinit()==ESP_FAIL && s_core_initialized && !log_live); ++ config_result=0;assert(ts_core_deinit()==0 && !s_core_initialized && !config_live); ++ s_core_cleanup_pending=false;log_live=true;config_live=true;log_result=ESP_FAIL; ++ assert(core_init_rollback(ESP_ERR_NO_MEM)==ESP_FAIL && s_core_cleanup_pending && config_live); ++ log_result=0;assert(ts_core_deinit()==0 && !s_core_cleanup_pending && !config_live); ++ puts("PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed"); ++} +--- /dev/null ++++ b/tests/ws_subscriptions/test_reviewer_http.c +@@ -0,0 +1,23 @@ ++#include "platform.h" ++#define HTTP_GET 0 ++#define HTTPD_500_INTERNAL_SERVER_ERROR 500 ++#define HTTPD_SOCK_ERR_TIMEOUT -3 ++#define TS_MALLOC_PSRAM malloc ++static bool s_stopping; ++static const char *status; ++static unsigned called,read_body; ++typedef struct{httpd_req_t*req;const char*uri;int method;char*body;size_t body_len;}ts_http_request_t; ++typedef struct{int(*handler)(ts_http_request_t*,void*);void*user_data;}ts_http_route_t; ++static int httpd_resp_set_status(httpd_req_t*r,const char*s){(void)r;status=s;return 0;} ++static int httpd_resp_sendstr(httpd_req_t*r,const char*s){(void)r;(void)s;return 0;} ++static int httpd_resp_send_err(httpd_req_t*r,int e,const char*s){(void)r;(void)e;(void)s;return 0;} ++static int httpd_req_recv(httpd_req_t*r,char*b,size_t n){(void)r;(void)b;(void)n;read_body++;return -1;} ++static int operation(ts_http_request_t*r,void*u){(void)r;(void)u;called++;return 0;} ++#include "reviewer_http.inc" ++int main(void){ ++ ts_http_route_t route={.handler=operation};httpd_req_t req={.method=1,.user_ctx=&route,.content_len=20}; ++ s_stopping=true;assert(http_handler_wrapper(&req)==0 && !strcmp(status,"503 Service Unavailable") && !called && !read_body); ++ req.method=HTTP_GET;req.content_len=0;assert(http_handler_wrapper(&req)==0 && called==1); ++ s_stopping=false;req.method=1;assert(http_handler_wrapper(&req)==0 && called==2); ++ puts("PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid"); ++} +--- /dev/null ++++ b/tests/ws_subscriptions/test_reviewer_service.c +@@ -0,0 +1,30 @@ ++#include "platform.h" ++#define ESP_LOGI(...) ((void)0) ++#define ESP_LOGW(...) ((void)0) ++#define TS_SERVICE_PHASE_MAX 2 ++#define TS_EVENT_BASE_SERVICE "service" ++#define TS_EVENT_SERVICE_STOPPED 1 ++typedef enum {TS_SERVICE_STATE_REGISTERED,TS_SERVICE_STATE_RUNNING,TS_SERVICE_STATE_STOPPING,TS_SERVICE_STATE_STOPPED} ts_service_state_t; ++typedef struct svc {struct{const char*name;int phase;int(*stop)(void*,void*);void*user_data;}def;ts_service_state_t state;SemaphoreHandle_t state_sem;struct svc*next;} ts_service_instance_t; ++typedef void* ts_service_handle_t; ++typedef struct{const char*service_name;ts_service_state_t old_state,new_state;int error_code;} ts_service_event_data_t; ++static struct{bool initialized,startup_complete;SemaphoreHandle_t mutex;ts_service_instance_t*services;unsigned service_count;}s_svc_ctx; ++static void set_service_state(ts_service_instance_t*s,ts_service_state_t state){s->state=state;} ++static int stop_service_internal(ts_service_instance_t*); ++int ts_service_stop(ts_service_handle_t); ++int ts_service_stop_all(void); ++#include "reviewer_service.inc" ++static unsigned ui_calls,net_calls; ++static int ui_result=ESP_ERR_TIMEOUT; ++static int busy_ui(void*h,void*u){(void)h;(void)u;ui_calls++;return ui_result;} ++static int stop_net(void*h,void*u){(void)h;(void)u;net_calls++;return ESP_OK;} ++int main(void){ ++ ts_service_instance_t*ui=calloc(1,sizeof(*ui)),*net=calloc(1,sizeof(*net)); ++ ui->def.name="webui";ui->def.phase=1;ui->def.stop=busy_ui;ui->state=TS_SERVICE_STATE_RUNNING;ui->next=net; ++ net->def.name="network";net->def.phase=0;net->def.stop=stop_net;net->state=TS_SERVICE_STATE_RUNNING; ++ s_svc_ctx.initialized=true;s_svc_ctx.startup_complete=true;s_svc_ctx.mutex=xSemaphoreCreateMutex();s_svc_ctx.services=ui;s_svc_ctx.service_count=2; ++ assert(ts_service_stop_all()==ESP_ERR_TIMEOUT);assert(ui->state==TS_SERVICE_STATE_RUNNING && net_calls==0); ++ assert(ts_service_deinit()==ESP_ERR_TIMEOUT && s_svc_ctx.initialized && s_svc_ctx.services==ui); ++ ui_result=ESP_OK;assert(ts_service_deinit()==ESP_OK && !s_svc_ctx.initialized && !s_svc_ctx.services && net_calls==1); ++ puts("PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership"); ++} diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/reviewer-tests.txt b/docs/repair/ws-subscriptions/reviewer-fixes/reviewer-tests.txt new file mode 100644 index 0000000..dc04122 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/reviewer-tests.txt @@ -0,0 +1,17 @@ +PASS R1: busy stop retains real worker; final fanout drains with no new producer message +PASS R1 timeout: handler-barrier and transport-drain failures retain worker; accepted fanout progresses before retry +PASS R3: real role change drops old queued logs, including unsubscribe/resubscribe ABA +PASS R2: task-create failure/early close never end as connected; reserved failure survives normal pool saturation and SDK queue rejection; late READY invalid +PASS R2 exec: admitted result reservation survives ordinary saturation and preserves recipients at completion +R5 observed system.dashboard: 75 delivered frames +R5 observed system.info: 75 delivered frames +R5 observed system.memory: 75 delivered frames +R5 observed system.cpu: 75 delivered frames +R5 observed network.status: 75 delivered frames +R5 observed power.status: 75 delivered frames +R5 observed fan.status: 75 delivered frames +R5 observed service.list: 75 delivered frames +PASS R5: all eight topics progress under six-slot pressure; no API collection without message/descriptor/byte capacity +PASS R4 service: stop errors retain registry/dependencies; retry drains then releases ownership +PASS R4 core: real event drain timeout retains downstream resources; service/config/log errors propagate; partial deinit retries succeed +PASS R1 HTTP admission: stopping rejects writes before body/handler execution; reads and resumed admission remain valid diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/runtime.txt b/docs/repair/ws-subscriptions/reviewer-fixes/runtime.txt new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/runtime.txt @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/core_stop.c b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/core_stop.c new file mode 100644 index 0000000..60fb715 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/core_stop.c @@ -0,0 +1,53 @@ +#define TEST_REAL_EVENT +#include "platform.h" +#include +#include "ts_event.c" +int64_t test_now; +TaskHandle_t xTaskGetCurrentTaskHandle(void){return (void*)pthread_self();} +int xTaskCreate(void(*fn)(void*),const char*n,unsigned s,void*a,unsigned p,TaskHandle_t*out){(void)fn;(void)n;(void)s;(void)a;(void)p;*out=(void*)1;return pdPASS;} +void vTaskDelete(TaskHandle_t t){(void)t;} +void vTaskDelay(TickType_t t){test_now+=(int64_t)t*1000;} +static pthread_mutex_t barrier=PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cv=PTHREAD_COND_INITIALIZER; +static bool entered,release_callback; +static void blocked(const ts_event_t*e,void*u){(void)e;(void)u;pthread_mutex_lock(&barrier);entered=true;pthread_cond_broadcast(&cv);while(!release_callback)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier);} +static void*post(void*p){(void)p;ts_event_post_sync("test",1,NULL,0);return NULL;} +static bool s_core_initialized=true,s_core_started=false,log_freed,config_freed; +static int ts_core_stop(void){return 0;} +static int ts_service_deinit(void){return 0;} +static int ts_log_deinit(void){log_freed=true;return 0;} +static int ts_config_deinit(void){config_freed=true;return 0;} +esp_err_t ts_core_deinit(void) +{ + if (!s_core_initialized) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGI(TAG, "Deinitializing TianShanOS Core..."); + + // 如果已启动,先停止 + if (s_core_started) { + ts_core_stop(); + } + + // 按相反顺序反初始化 + ts_service_deinit(); + ts_event_deinit(); + ts_log_deinit(); + ts_config_deinit(); + + s_core_initialized = false; + ESP_LOGI(TAG, "TianShanOS Core deinitialized"); + + return ESP_OK; +} +int main(void){ + s_event_ctx.initialized=true;s_event_ctx.running=true;s_event_ctx.mutex=xSemaphoreCreateMutex();s_event_ctx.event_queue=xQueueCreate(4,1); + ts_event_handler_handle_t h;assert(ts_event_register("test",1,blocked,NULL,&h)==0); + pthread_t thread;pthread_create(&thread,NULL,post,NULL); + pthread_mutex_lock(&barrier);while(!entered)pthread_cond_wait(&cv,&barrier);pthread_mutex_unlock(&barrier); + int result=ts_core_deinit();assert(result==ESP_OK && !s_core_initialized && log_freed && config_freed && s_event_ctx.initialized && s_dispatch_scopes); + printf("CONFIRMED R4: actual event drain timed out at %lld us, but actual core_deinit returned OK and deinitialized log/config while callback was still running\n",(long long)test_now); + pthread_mutex_lock(&barrier);release_callback=true;pthread_cond_broadcast(&cv);pthread_mutex_unlock(&barrier);pthread_join(thread,NULL); + assert(ts_event_unregister_sync(h,0)==0);assert(ts_event_deinit()==0); +} diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/evidence.txt b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/evidence.txt new file mode 100644 index 0000000..8e2c2b3 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/evidence.txt @@ -0,0 +1,11 @@ +CONFIRMED R4: actual event drain timed out at 6000000 us, but actual core_deinit returned OK and deinitialized log/config while callback was still running +CONFIRMED R4 aggregate: failed WebUI stop was ignored; lower-phase dependency stopped; service_deinit released registry and returned OK despite repeated failure +system.dashboard: api=100 serialized=100 +system.info: api=100 serialized=100 +system.memory: api=100 serialized=100 +system.cpu: api=100 serialized=100 +network.status: api=100 serialized=100 +power.status: api=100 serialized=100 +fan.status: api=100 serialized=0 +service.list: api=100 serialized=0 +CONFIRMED R5: fan/status and service/list starve for 100 completed cycles, although their APIs are collected each time diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/review.md b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/review.md new file mode 100644 index 0000000..216733f --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/review.md @@ -0,0 +1,45 @@ +# 第二轮 Reviewer 复核 — 2026-09-25 + +结论:需修复后交付。新增 2 项确认问题,合并上一轮为 5 项。未修改仓库文件。本轮并非宣布不存在其他问题。 + +HEAD 仍为 35238b4645ae5e9e0e99555d4fb64080d945565c;当前修复仍未提交。第一轮 R1 停止失败后发送停滞、R2 SSH 错误终态丢失、R3 日志角色失效未撤销,继续保留。第一轮记录:/tmp/ts-review-ws/review.md。 + +## R4 / P1:新增停止失败契约没有贯穿服务和核心调用链 + +源码:components/ts_core/ts_service/src/ts_service.c:383、147;main/ts_core_init.c:175(同函数还忽略 service_deinit 返回);main/ts_services.c:950 为 WebUI 真实服务停止入口。 + +WebUI 和事件总线现在可能返回 busy/timeout 并保留活跃对象,这是正确的底层契约。但 ts_service_stop_all 忽略单项失败,继续停止低阶段依赖,最后返回成功;ts_service_deinit 不检查 stop_all 结果,继续释放服务登记表和锁;ts_core_deinit 忽略事件排空超时,继续销毁日志、配置并清除核心初始化标志。结果是“底层仍活跃,上层已宣布关闭/释放”。本轮修改的安全停止只落实了下层,未覆盖这些现有调用者。 + +证据 A:生产 stop_service_internal / ts_service_stop / ts_service_stop_all / ts_service_deinit 原函数体,外围 RTOS 和服务回调模拟。WebUI 停止回调返回 TIMEOUT,单项状态正确保持 RUNNING,但 stop_all 返回 OK 并执行低阶段服务停止;deinit 再次遇到失败仍释放登记表并返回 OK。 + +证据 B:完整生产 ts_event.c 与实际 ts_core_deinit 函数体。pthread 屏障保留一个在途同步事件回调,虚拟时钟推进到 6 秒,真实事件 deinit 超时。真实 core_deinit 仍返回 OK,已调用模拟的日志/配置销毁,核心标志 false,而事件系统仍 initialized 且回调仍在途。测试随后正常释放屏障并排空,没有真实设备操作。 + +性质:吞错代码原已存在;这是本次引入可重试停止后未迁移完整调用链的缺口,不应宣称这些行是本次新增代码。并不意味着用户每次关机都触发;条件是停止/排空失败时走聚合停止或核心反初始化入口。 + +最小修复:向上传递失败,保留重试所需的服务状态与控制资源,遇到仍依赖下层资源的活跃服务时不要继续销毁其依赖;核心不应在事件排空失败后销毁日志/配置或清除 initialized。保持原有停机顺序,不扩展为框架改造。 + +回归门槛:将 WebUI busy/timeout 注入真实聚合停止链;事件回调未退出时触发核心 deinit;确认返回失败、资源保留、依赖仍在,以及回调结束后重试成功。 + +## R5 / P2:消息预算与固定调度顺序导致后部主题饥饿 + +源码:components/ts_webui/src/ts_ws_subscriptions.c:190、158–179;components/ts_webui/src/ts_ws_transport.c:133–134。 + +周期消息只有 6 个槽;run_batch 只把 message_capacity 当作有/无开关,然后按描述符数预留到期目标;collect_batch 固定按 8 个主题的顺序采集/组包。若同批包含 8 个独立周期主题,且 HTTPD 在该批组包结束后才排空,前 6 个占满消息槽,后 2 个分配失败。它们已经付出了 API 采集成本,却被当作失败再延后完整 interval;下一批仍按相同顺序竞争,缺乏公平进展保证。 + +证据:完整生产 manager + transport C;单连接订阅所有 8 个周期主题,interval 均为合法的 10000 ms;控制时钟与调度,使同批到期、批末排空。100 轮中前 6 个主题各序列化 100 次,fan.status/service.list 各序列化 0 次,但对应 API 各调用 100 次。没有持续堆分配失败、无穷输入或无限慢连接。 + +证据边界:这是合法受控调度下的确定性反例,不表示真实板上每种调度都必然连续丢 100 轮;实际 HTTPD 若在组包中途释放槽可能改变结果。反例证明当前实现没有公平进展保证。 + +最小修复:采集前同时按独立消息数、描述符预算选择本批主题,并让未获容量的主题公平获得后续机会;容量不足不要伪装成一次已尝试后的完整周期失败。优先复用现有 worker、表和通知,不靠单纯扩容遮蔽固定顺序问题。 + +回归门槛:8 个合法主题同批到期,消息容量小于主题数;慢消费者与不同 interval 混合;确认每个有效主题最终有进展,无消息预算时不重复采集必然丢弃的数据。 + +## 本轮执行和未执行 + +- /tmp/ts-review-ws-round2/core_stop:ASan/UBSan;确认真实事件超时未传递到核心关闭结果。 +- /tmp/ts-review-ws-round2/service_stop:ASan/UBSan;确认聚合停止/反初始化忽略失败。 +- /tmp/ts-review-ws-round2/starvation:ASan/UBSan;确认 100 轮主题饥饿。 +- 三者退出 0 表示反例成立,不表示产品验收通过。生产逻辑来自当前文件 include 或原函数体提取;依赖和时间/线程屏障受控。 +- git diff --check:退出 0。 +- 未修改生产代码,未重复固件构建或浏览器测试;没有设备、远端 SSH、刷机、重启、commit/push/PR 操作。 +- 事件节点选中后注销、自注销、同步排空和超时保活路径继续检查,未确认独立的新节点回收缺陷。完整全局事件总线销毁与外部生产者并发准入仍不属于已证明安全的范围;不要把 handler 排空测试等同于全局销毁并发验收。 diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/run.sh b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/run.sh new file mode 100644 index 0000000..fdadf6b --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/run.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -euo pipefail +cd /Users/massif/TianshanOS +export DEVELOPER_DIR=/Library/Developer/CommandLineTools +cjson=/Users/massif/esp/v5.5.2/esp-idf/components/json/cJSON +cc -std=gnu11 -g -fsanitize=address,undefined -Wno-deprecated-declarations -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" /tmp/ts-review-ws-round2/starvation.c "$cjson/cJSON.c" -o /tmp/ts-review-ws-round2/starvation +cc -std=gnu11 -g -fsanitize=address,undefined -Wno-deprecated-declarations -Icomponents/ts_core/ts_event/include -Itests/ws_subscriptions/stubs -Icomponents/ts_core/ts_event/src -I"$cjson" /tmp/ts-review-ws-round2/core_stop.c -o /tmp/ts-review-ws-round2/core_stop +cc -std=gnu11 -g -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -I"$cjson" /tmp/ts-review-ws-round2/service_stop.c -o /tmp/ts-review-ws-round2/service_stop +/tmp/ts-review-ws-round2/core_stop +/tmp/ts-review-ws-round2/service_stop +/tmp/ts-review-ws-round2/starvation diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/service_stop.c b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/service_stop.c new file mode 100644 index 0000000..103c6e5 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/service_stop.c @@ -0,0 +1,161 @@ +#include "platform.h" +#define ESP_LOGI(...) ((void)0) +#define ESP_LOGW(...) ((void)0) +#define TS_SERVICE_PHASE_MAX 2 +#define TS_EVENT_BASE_SERVICE "service" +#define TS_EVENT_SERVICE_STOPPED 1 +typedef enum {TS_SERVICE_STATE_REGISTERED,TS_SERVICE_STATE_RUNNING,TS_SERVICE_STATE_STOPPING,TS_SERVICE_STATE_STOPPED} ts_service_state_t; +typedef struct svc {struct{const char*name;int phase;int(*stop)(void*,void*);void*user_data;}def;ts_service_state_t state;SemaphoreHandle_t state_sem;struct svc*next;} ts_service_instance_t; +typedef void* ts_service_handle_t; +typedef struct{const char*service_name;ts_service_state_t old_state,new_state;int error_code;} ts_service_event_data_t; +static struct{bool initialized,startup_complete;SemaphoreHandle_t mutex;ts_service_instance_t*services;unsigned service_count;}s_svc_ctx; +static void set_service_state(ts_service_instance_t*s,ts_service_state_t state){s->state=state;} +static int stop_service_internal(ts_service_instance_t*); +int ts_service_stop(ts_service_handle_t); +int ts_service_stop_all(void); +static esp_err_t stop_service_internal(ts_service_instance_t *service) +{ + if (service == NULL) { + return ESP_ERR_INVALID_ARG; + } + + // 已经停止 + if (service->state == TS_SERVICE_STATE_STOPPED || + service->state == TS_SERVICE_STATE_REGISTERED) { + return ESP_OK; + } + + // 不能停止非运行状态的服务 + if (service->state != TS_SERVICE_STATE_RUNNING) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGI(TAG, "Stopping service: %s", service->def.name); + + ts_service_state_t old_state = service->state; + set_service_state(service, TS_SERVICE_STATE_STOPPING); + + esp_err_t ret = ESP_OK; + + // 调用停止回调 + if (service->def.stop != NULL) { + ret = service->def.stop(service, service->def.user_data); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Service '%s' stop returned error: %s", + service->def.name, esp_err_to_name(ret)); + /* Failed stop retains the service and its resources for a later retry. */ + set_service_state(service, old_state); + return ret; + } + } + + set_service_state(service, TS_SERVICE_STATE_STOPPED); + + ESP_LOGI(TAG, "Service '%s' stopped", service->def.name); + + // 发送服务停止事件 + ts_service_event_data_t event_data = { + .service_name = service->def.name, + .old_state = old_state, + .new_state = TS_SERVICE_STATE_STOPPED, + .error_code = ret, + }; + ts_event_post(TS_EVENT_BASE_SERVICE, TS_EVENT_SERVICE_STOPPED, + &event_data, sizeof(event_data), 100); + + return ESP_OK; +} +esp_err_t ts_service_stop(ts_service_handle_t handle) +{ + if (handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (!s_svc_ctx.initialized) { + return ESP_ERR_INVALID_STATE; + } + + ts_service_instance_t *service = (ts_service_instance_t *)handle; + return stop_service_internal(service); +} +esp_err_t ts_service_stop_all(void) +{ + if (!s_svc_ctx.initialized) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGI(TAG, "Stopping all services..."); + + // 按相反顺序停止(从 UI 到 PLATFORM) + for (int phase = TS_SERVICE_PHASE_MAX - 1; phase >= 0; phase--) { + ESP_LOGI(TAG, "Stopping phase: %s", ts_service_phase_to_string(phase)); + + xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); + + ts_service_instance_t *service = s_svc_ctx.services; + while (service != NULL) { + if (service->def.phase == phase && + service->state == TS_SERVICE_STATE_RUNNING) { + xSemaphoreGive(s_svc_ctx.mutex); + ts_service_stop(service); + xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); + } + service = service->next; + } + + xSemaphoreGive(s_svc_ctx.mutex); + } + + s_svc_ctx.startup_complete = false; + ESP_LOGI(TAG, "All services stopped"); + + return ESP_OK; +} +esp_err_t ts_service_deinit(void) +{ + if (!s_svc_ctx.initialized) { + return ESP_ERR_INVALID_STATE; + } + + ESP_LOGI(TAG, "Deinitializing service management..."); + + // 停止所有服务 + ts_service_stop_all(); + + xSemaphoreTake(s_svc_ctx.mutex, portMAX_DELAY); + + // 释放所有服务 + ts_service_instance_t *service = s_svc_ctx.services; + while (service != NULL) { + ts_service_instance_t *next = service->next; + if (service->state_sem != NULL) { + vSemaphoreDelete(service->state_sem); + } + free(service); + service = next; + } + s_svc_ctx.services = NULL; + s_svc_ctx.service_count = 0; + + xSemaphoreGive(s_svc_ctx.mutex); + + vSemaphoreDelete(s_svc_ctx.mutex); + s_svc_ctx.mutex = NULL; + + s_svc_ctx.initialized = false; + ESP_LOGI(TAG, "Service management deinitialized"); + + return ESP_OK; +} +static unsigned ui_calls,net_calls; +static int busy_ui(void*h,void*u){(void)h;(void)u;ui_calls++;return ESP_ERR_TIMEOUT;} +static int stop_net(void*h,void*u){(void)h;(void)u;net_calls++;return ESP_OK;} +int main(void){ + ts_service_instance_t*ui=calloc(1,sizeof(*ui)),*net=calloc(1,sizeof(*net)); + ui->def.name="webui";ui->def.phase=1;ui->def.stop=busy_ui;ui->state=TS_SERVICE_STATE_RUNNING;ui->next=net; + net->def.name="network";net->def.phase=0;net->def.stop=stop_net;net->state=TS_SERVICE_STATE_RUNNING; + s_svc_ctx.initialized=true;s_svc_ctx.startup_complete=true;s_svc_ctx.mutex=xSemaphoreCreateMutex();s_svc_ctx.services=ui;s_svc_ctx.service_count=2; + assert(ts_service_stop_all()==ESP_OK);assert(ui->state==TS_SERVICE_STATE_RUNNING && net_calls==1); + assert(ts_service_deinit()==ESP_OK && !s_svc_ctx.initialized && !s_svc_ctx.services && ui_calls==2); + puts("CONFIRMED R4 aggregate: failed WebUI stop was ignored; lower-phase dependency stopped; service_deinit released registry and returned OK despite repeated failure"); +} diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/starvation.c b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/starvation.c new file mode 100644 index 0000000..36a319b --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws-round2/starvation.c @@ -0,0 +1,13 @@ +#define main existing_main +#include "/Users/massif/TianshanOS/tests/ws_subscriptions/test_manager.c" +#undef main +int main(void){ + cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); + start();ts_ws_peer_t a=open_peer(1); + for(unsigned i=0;i<8;i++)subscribe(a,topics[i].name,10000); + for(unsigned n=0;n<100;n++){test_now+=10000000;run_batch();pump();} + for(unsigned i=0;i<8;i++)printf("%s: api=%llu serialized=%llu\n",topics[i].name,(unsigned long long)(i?s_stats.api[topics[i].metric]:s_stats.api[0]),(unsigned long long)s_stats.serialized[i]); + assert(s_stats.serialized[5]==100 && s_stats.serialized[6]==0 && s_stats.serialized[7]==0); + puts("CONFIRMED R5: fan/status and service/list starve for 100 completed cycles, although their APIs are collected each time"); + stop();assert(!live_allocations); +} diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/evidence.txt b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/evidence.txt new file mode 100644 index 0000000..46fe71d --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/evidence.txt @@ -0,0 +1,3 @@ +CONFIRMED R1: stop returned busy; worker absent; accepted two-recipient message sent to only one; pending jobs=1 +CONFIRMED R2: three real ssh_send_status calls produce two frames; final frame={"type":"ssh_status","status":"connected","message":"SSH shell ready"} +CONFIRMED R3: actual terminal_start changes client role, but both queued and new log frames still reach this peer diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/review.c b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/review.c new file mode 100644 index 0000000..ed938d4 --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/review.c @@ -0,0 +1,200 @@ +#define main original_manager_main +#include "/Users/massif/TianshanOS/tests/ws_subscriptions/test_manager.c" +#undef main +static bool s_ws_stopping, s_exec_running, s_ssh_poll_alive; +static unsigned s_exec_creators; +static ts_event_handler_handle_t s_power_event_handle; +static ts_ws_peer_t s_ssh_peer; +static int s_ssh_client_fd; +static httpd_handle_t s_server=(void*)11; +static void ssh_cleanup(void) {} +esp_err_t ts_webui_ws_stop(httpd_handle_t server) +{ + if (ts_ws_transport_in_context() || ts_event_in_callback()) return ESP_ERR_INVALID_STATE; + s_ws_stopping = true; + esp_err_t ret = ts_ws_subscriptions_deinit(); + if (ret != ESP_OK) return ret; + ret = ts_ws_transport_quiesce(server, 6000); + if (ret != ESP_OK) return ret; + if (s_power_event_handle) { + ret = ts_event_unregister_sync(s_power_event_handle, 6000); + if (ret != ESP_OK && ret != ESP_ERR_NOT_FOUND) return ret; + s_power_event_handle = NULL; + } + /* Do not destroy a running remote operation or replay it. Keep HTTPD alive + * and return busy; the control caller can retry after its normal completion. */ + if (s_exec_creators || s_exec_running) return ESP_ERR_INVALID_STATE; + ssh_cleanup(); + if (s_ssh_poll_alive) return ESP_ERR_TIMEOUT; + return ts_ws_transport_stop(server, 6000); +} +#define free tracked_free +static void ssh_send_status(const char *status, const char *message) +{ + if (s_ssh_client_fd < 0 || !s_server) return; + + cJSON *msg = cJSON_CreateObject(); + cJSON_AddStringToObject(msg, "type", "ssh_status"); + cJSON_AddStringToObject(msg, "status", status); + if (message) { + cJSON_AddStringToObject(msg, "message", message); + } + + char *json = cJSON_PrintUnformatted(msg); + cJSON_Delete(msg); + + if (json) { + httpd_ws_frame_t ws_pkt = { + .type = HTTPD_WS_TYPE_TEXT, + .payload = (uint8_t *)json, + .len = strlen(json) + }; + ts_ws_message_t *owned = ts_ws_message_text((const char *)ws_pkt.payload, ws_pkt.len); + if (owned) { + ts_ws_transport_submit(s_ssh_peer, owned, 0, 0, NULL, NULL); + ts_ws_message_release(owned); + } + free(json); + } +} + +#undef free + +#define MAX_WS_CLIENTS TS_WS_CONNECTIONS +enum { WS_CLIENT_TYPE_EVENT, WS_CLIENT_TYPE_TERMINAL, WS_CLIENT_TYPE_SSH_SHELL, WS_CLIENT_TYPE_LOG }; +static struct {bool active;int fd;httpd_handle_t hd;int type;} s_clients[MAX_WS_CLIENTS]; +static int s_terminal_client_fd=-1; +static void ts_console_clear_output_cb(void){} +static void terminal_output_cb(const char *d,size_t n,void *u){(void)d;(void)n;(void)u;} +static void ts_console_set_output_cb(void(*fn)(const char*,size_t,void*),void*u){(void)fn;(void)u;} +static void cleanup_disconnected_client(int fd){(void)fd;} +static int httpd_ws_send_frame(httpd_req_t*r,httpd_ws_frame_t*f){return httpd_ws_send_frame_async(r->handle,r->fd,f);} +#define free tracked_free +static void start_terminal_session(httpd_req_t *req) +{ + int fd = httpd_req_to_sockfd(req); + + // 检查是否有其他终端会话 + if (s_terminal_client_fd >= 0 && s_terminal_client_fd != fd) { + // 检查旧的终端 fd 是否还在活跃客户端列表中 + bool old_fd_active = false; + httpd_handle_t old_hd = NULL; + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == s_terminal_client_fd) { + old_fd_active = true; + old_hd = s_clients[i].hd; + break; + } + } + + // 如果旧的 fd 已经不活跃(例如页面刷新),强制清理 + if (!old_fd_active) { + TS_LOGW(TAG, "Terminal session orphaned (fd=%d), cleaning up", s_terminal_client_fd); + ts_console_clear_output_cb(); + s_terminal_client_fd = -1; + } else { + // 旧会话仍在列表中 + // 采用宽松策略:新的终端请求优先,主动关闭旧会话 + // 原因:通常是用户刷新页面或网络重连,旧会话应该让位 + TS_LOGI(TAG, "Terminal takeover: closing old session (fd=%d) for new request (fd=%d)", + s_terminal_client_fd, fd); + + // 向旧会话发送关闭通知 + cJSON *close_msg = cJSON_CreateObject(); + cJSON_AddStringToObject(close_msg, "type", "session_closed"); + cJSON_AddStringToObject(close_msg, "reason", "Another terminal session requested"); + char *close_json = cJSON_PrintUnformatted(close_msg); + cJSON_Delete(close_msg); + + if (close_json) { + httpd_ws_frame_t ws_pkt = { + .type = HTTPD_WS_TYPE_TEXT, + .payload = (uint8_t *)close_json, + .len = strlen(close_json) + }; + ts_ws_transport_send(old_hd, s_terminal_client_fd, &ws_pkt); + free(close_json); + } + + // 清理旧会话 + cleanup_disconnected_client(s_terminal_client_fd); + s_terminal_client_fd = -1; + + // 短暂延迟确保关闭消息发送 + vTaskDelay(pdMS_TO_TICKS(50)); + } + } + + // 设置为终端客户端 + for (int i = 0; i < MAX_WS_CLIENTS; i++) { + if (s_clients[i].active && s_clients[i].fd == fd) { + s_clients[i].type = WS_CLIENT_TYPE_TERMINAL; + break; + } + } + + // 设置输出回调 + s_terminal_client_fd = fd; + ts_console_set_output_cb(terminal_output_cb, NULL); + + // 发送确认消息和欢迎信息 + cJSON *welcome = cJSON_CreateObject(); + cJSON_AddStringToObject(welcome, "type", "connected"); + cJSON_AddStringToObject(welcome, "message", "Terminal session started"); + cJSON_AddStringToObject(welcome, "prompt", "tianshan> "); + char *json = cJSON_PrintUnformatted(welcome); + cJSON_Delete(welcome); + + if (json) { + httpd_ws_frame_t ws_pkt = { + .type = HTTPD_WS_TYPE_TEXT, + .payload = (uint8_t *)json, + .len = strlen(json) + }; + httpd_ws_send_frame(req, &ws_pkt); + free(json); + } + + TS_LOGD(TAG, "Terminal session started (fd=%d)", fd); +} +#undef free + +static void sdk_one(void) { + if(!queued)return; + current=(void*)3;typeof(queue[0]) q=queue[0];memmove(queue,queue+1,--queued*sizeof(queue[0]));q.fn(q.arg);current=(void*)1; +} +static void stop_progress(void){worker_exit();sdk_one();} +int main(void) { + cJSON_Hooks hooks={tracked_malloc,tracked_free};cJSON_InitHooks(&hooks); + start();s_ssh_peer=open_peer(1);s_ssh_client_fd=1;open_peer(2); + s_exec_running=true;delay_hook=stop_progress; + int ret=ts_webui_ws_stop((void*)11);delay_hook=NULL; + assert(ret==ESP_ERR_INVALID_STATE && !s_worker && s_state==OFF); + httpd_ws_frame_t f={.payload=(uint8_t*)"{}",.len=2}; + assert(ts_ws_transport_broadcast(&f)==ESP_OK); + sdk_one(); + assert(queued==0 && ts_ws_transport_needs_flush() && frames[1]==1 && frames[2]==0); + printf("CONFIRMED R1: stop returned busy; worker absent; accepted two-recipient message sent to only one; pending jobs=%u\n",s_tx_stats.jobs); + pump();s_exec_running=false;stop(); + start();s_ssh_peer=open_peer(1);s_ssh_client_fd=1; + unsigned before=frames[1]; + current=(void*)3; + ssh_send_status("connecting", "Connecting to SSH server..."); + ssh_send_status("connected", "SSH shell ready"); + ssh_send_status("error", "Failed to create SSH session"); + current=(void*)1;pump(); + assert(frames[1]==before+2 && strstr(payloads[1],"connected")); + printf("CONFIRMED R2: three real ssh_send_status calls produce two frames; final frame=%s\n",payloads[1]); + stop();assert(live_allocations==0); + start();ts_ws_peer_t peer=open_peer(1); + s_clients[0].active=true;s_clients[0].fd=1;s_clients[0].hd=peer.server;s_clients[0].type=WS_CLIENT_TYPE_LOG; + ts_ws_peer_log_level(peer,5); + httpd_ws_frame_t log={.payload=(uint8_t*)"old-log",.len=7};assert(ts_ws_transport_log(&log,3)==0); + current=(void*)3;start_terminal_session(&reqs[1]);current=(void*)1; + assert(s_clients[0].type==WS_CLIENT_TYPE_TERMINAL); + pump();assert(!strcmp(payloads[1],"old-log")); + assert(ts_ws_transport_log(&log,3)==0);pump();assert(!strcmp(payloads[1],"old-log")); + puts("CONFIRMED R3: actual terminal_start changes client role, but both queued and new log frames still reach this peer"); + stop();assert(live_allocations==0); + return 0; +} diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/review.md b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/review.md new file mode 100644 index 0000000..ec2492f --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/review.md @@ -0,0 +1,48 @@ +# WebSocket 本地修改独立复核 — 2026-09-25 + +结论:需修复后交付。前一轮“已完成”结论应撤回;当前确认 2 个 P1 和 1 个 P2,不表示不存在其他缺陷。 + +基线 HEAD:35238b4645ae5e9e0e99555d4fb64080d945565c。审查范围为当前未提交 WebSocket 修复及其事件总线、HTTP 生命周期、测试和交付记录;不是重审整个历史版本的所有代码。未修改仓库文件;反例仅保存在 /tmp/ts-review-ws。 + +## R1 / P1:停止失败后发送队列失去推进者 + +位置:components/ts_webui/src/ts_webui_ws.c:1149–1162;ts_ws_transport.c:247–254。 + +真实 ws_stop 先 deinit manager(worker 已退出),再检查 SSH exec。执行仍在进行时返回 INVALID_STATE,但保留 HTTPD 与后台执行。发送完成仅唤醒已不存在的 worker;SDK 不自动执行 PREPARED 描述符。没有后续提交/再次停止时,已接受的剩余消息可以永久滞留。停止返回超时的部分路径也有同类问题。 + +反例:抽取当前实际 ws_stop 函数体,联合完整生产 transport/manager C;模拟正在执行 SSH,停止返回 busy 后广播给两个连接。执行真实 SDK work 回调一次后,只有一个连接收到,另一个描述符仍待发,SDK 队列为空且 worker 为 NULL。测试没有用 pump() 自动替生产代码补 flush。 + +最低修复:拆开“关闭遥测准入”和“销毁发送推进者”的时序;所有可重试失败阶段,保留任务结果所需的发送推进能力。检查活动执行应在破坏其依赖之前完成,并继续考虑创建入口与停止的竞争。不能靠丢弃任务结果或要求用户重试停止才能恢复消息推进。 + +回归:真实停止 + 活动执行 + 多接收者 + 最后一条完成消息,停止失败后不再有新消息,仍应完成发送;覆盖 barrier 超时、轮询任务超时及重试。 + +## R2 / P1:SSH 错误终态被静默丢弃,最后收到的仍是 connected + +位置:components/ts_webui/src/ts_webui_ws.c:223–227、412–420;ts_ws_transport.c:129–140。 + +非遥测消息只有两个共享 message 槽。handle_ssh_connect 在同一个 HTTPD 请求中依次发送 connecting、connected;若创建轮询任务失败,还发送 error。前两条现在改为排队,HTTPD 当前请求没有返回前无法执行其队列回调;第三条分配必然失败。ssh_send_status 忽略分配/提交失败,错误没有发出,也没有记录拒绝。任务实际上未运行、资源已清理,客户端却最后看到 connected。其他日志占槽还会降低可用容量。 + +反例:执行从当前源码抽取的真实 ssh_send_status,联合完整生产 transport,模拟上述同一 HTTPD 请求内三个状态调用。只收到两帧,最后帧是 {"type":"ssh_status","status":"connected","message":"SSH shell ready"}。不依赖真实设备、网络拥塞或远端连接。 + +最低修复:在完整启动成功前不发 connected;复用 HTTPD 所有者上下文可安全同步发送的结构,或为关键终态设置独立有界保留和可观测的失败处理。不能仅增大两个槽的常量,也不能让日志/普通输出挤掉错误后继续显示成功。 + +回归:实际连接处理器的任务创建失败;日志占槽 + SSH 成功/失败/远端关闭;输出满载后的终态必须明确,拒绝可观察。本反例覆盖真实发送函数和同请求调用顺序,尚未模拟完整 SSH 连接处理器的所有依赖。 + +## R3 / P2:连接角色变化没有撤销新 transport 的日志资格 + +位置:components/ts_webui/src/ts_webui_ws.c:648、363、1255;ts_ws_transport.c:378–400。 + +旧日志发送按 s_clients.type == LOG 判断。新发送路径使用独立 s_log_levels;terminal_start / ssh_connect 只更改旧表中的 type,没有清除 transport 中的日志资格,也未同步日志流开关。同一连接从日志切到终端/SSH 后,已排队和后来新增的日志仍可发送,导致接收集合变化和不必要的设备工作。 + +反例:执行真实 start_terminal_session,联合完整生产 transport。旧表已变成 TERMINAL,但先前排队和此后提交的 log 都通过最终 log_allowed 校验并送达。外围 console 和请求发送接口模拟;没有复制终端角色切换逻辑。 + +最低修复:在现有角色切换处统一维护旧客户端类型、transport 日志资格及全局日志回调开关;最终发送检查使用同一有效状态。补日志→终端、日志→SSH、角色切换前已排队日志的交叉测试。 + +## 验证记录与边界 + +- bash tests/ws_subscriptions/run_host.sh:本轮重新运行,退出 0;manager/event/HTTP生命周期/WS init-stop 主机测试通过。 +- git diff --check:本轮退出 0。 +- bash /tmp/ts-review-ws/run.sh:ASan/UBSan 编译运行真实生产 C 与抽取的真实函数体,三个缺陷断言成立,退出 0。这里退出 0 表示成功证明缺陷,绝不表示修复验收通过。 +- 现有 test_init 的停止依赖由 mock 分隔,test_manager 的 pump 主动 flush,所以没有覆盖 R1 的实际组合。现有测试未覆盖 R2 同一请求内的三状态路径或 R3 角色交叉。这解释了“既有回归通过”和“新增反例失败语义”可同时成立。 +- 本轮没有修改生产代码、重新构建固件或重跑浏览器;前一轮构建记录不能证明上述语义正确。 +- 没有连接设备、远端 SSH、刷机、重启、提交、推送或 PR 操作。RTOS 双核调度、真实慢网络、栈水位、长期运行及硬件告警仍需设备验收。 diff --git a/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/run.sh b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/run.sh new file mode 100644 index 0000000..394817a --- /dev/null +++ b/docs/repair/ws-subscriptions/reviewer-fixes/ts-review-ws/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail +cd /Users/massif/TianshanOS +export DEVELOPER_DIR=/Library/Developer/CommandLineTools +cjson=/Users/massif/esp/v5.5.2/esp-idf/components/json/cJSON +cc -std=gnu11 -g -Wno-deprecated-declarations -fsanitize=address,undefined -Itests/ws_subscriptions/stubs -Icomponents/ts_webui/include -Icomponents/ts_webui/src -I"$cjson" /tmp/ts-review-ws/review.c "$cjson/cJSON.c" -o /tmp/ts-review-ws/review +/tmp/ts-review-ws/review diff --git a/docs/repair/xterm-local/README.md b/docs/repair/xterm-local/README.md new file mode 100644 index 0000000..9e7c13d --- /dev/null +++ b/docs/repair/xterm-local/README.md @@ -0,0 +1,58 @@ +# Web Terminal xterm 本地化 + +基线 633bb94df3e1e454929a14257c06c307c09100e6;当前 PR #42 分支。初始工作区与原未跟踪文件见 baseline.txt;原 output/、tmp/、runtime-repair 未跟踪文件保持原样并排除提交。 + +## 生产修改与边界 + +- `components/ts_webui/web/js/terminal.js`:仅三个 loader URL 改为同源 vendor + TS_ASSET_VERSION;保留按需 Promise、去重、失败 UI/重试及 destroy 防护。J1、SSH、输入、终态等行为未改。 +- `components/ts_webui/web/index.html`:原缓存标识统一更新到 20260928-local-xterm。 +- `components/ts_webui/web/vendor/xterm/`:三个发行文件和两个独立 MIT LICENSE,完整来源/版本/原路径/SHA256/大小见 [vendor.json](vendor.json)。开发阶段从原运行时固定版本 jsDelivr 地址一次性取得;构建不下载依赖。无 map、src、typings、npm 包或缓存。 +- `tools/minify_web.py`:两个 JS/CSS 循环各增加 vendor 目录跳过;后续 gzip 不变。 + +CMake、SDK 配置、版本、发布流程、后端、SSH、硬件保护和前端布局均未修改。 + +### 经用户确认的路径调整 + +当前 SPIFFS 路径含目录最多 32 字节。原建议 addon 与许可证长路径实际导致 SDK 失败,证据见 path-limit.txt 和 initial-build-path-failure.log。用户确认后仅改为 `vendor/xterm/fit.min.js` 与 `vendor/xterm/LICENSE-fit`,其字节和版本不变。旧失败目录存在缓存的 GLOB 名称,因此最终使用全新独立目录 `/tmp/tianshan-xterm-final/build`,没有改 CMake 或文件系统格式。 + +## 版本、许可证和静态资源占用 + +| 文件 | 版本 | raw 字节 | gzip 字节 | +|---|---|---:|---:| +| xterm.min.js | xterm 5.3.0 | 283670 | 65684 | +| xterm.css | xterm 5.3.0 | 5383 | 2037 | +| fit.min.js | xterm-addon-fit 0.8.0 | 1789 | 822 | +| 合计运行时资源 | 固定版本 | 290842 | 68543 | + +两个 LICENSE 共 2364 字节;含许可证 vendor 原始总计 293206 字节。源码 vendor 与 web_optimized 未 gzip 文件逐字节相同,gunzip 后也逐字节相同。两份 MIT 版权信息保留。 + +SPIFFS 同时包含 raw、gzip 和许可证:新增文件数据合计 361749 字节(不含文件系统元数据)。生成器已分配 676/768 个 4096 字节块,未分配 92 块(376832 字节)。这是生成器布局统计,不等于运行时 ESP SPIFFS free API;未声称固定 3 MiB 镜像文件大小就是实际新增占用。构建未溢出,仍需设备挂载验收。 + +## 本次验证与重复入口 + +1. `node --test tests/prompts/xterm-vendor.test.cjs`:固定 SHA256、skip-minify/gzip identity、生产 loader 冷启动、共享 Promise、失败后重试通过。见 vendor-test.txt。 +2. `npm run test:xterm --prefix tests/prompts`:Node 专项及双语 Chrome 通过,见 offline-source.txt。全新 context 禁止 Service Worker、全部非 fixture origin 拦截;未注入 Terminal/FitAddon。真实 Terminal 构造、FitAddon、页面初始化、真实键盘输入、SSH、J1、退出、销毁和重入通过。 +3. 原 WebUI Node 40 项、Chrome 38 项重新执行通过,见 node.txt、browser.txt。原资源失败/重试测试改为本地文件故障注入,恢复后使用真实 bundle;未弱化断言。 +4. J1 专项通过,见 j1.txt。实际 C→JS→C v3 双语回归通过,见 cross-en/zh.txt/json,保留 H1、控制归属、取消/回收等既有断言。 +5. 固定 ESP-IDF v5.5.2 / ESP32-S3,独立目录全量 `idf.py -B /tmp/tianshan-xterm-final/build -D SDKCONFIG=/tmp/tianshan-xterm-final/sdkconfig build` 成功,见 build.log。日志刷机命令只是 SDK 输出,没有执行。 +6. `PROJECT_WEB_ROOT=/tmp/tianshan-xterm-final/build/esp-idf/ts_webui/web_optimized OFFLINE_RESULTS=docs/repair/xterm-local/optimized node --test tests/prompts/xterm-offline.test.cjs`:本次打包资源双语离线回放通过,见 offline-optimized.txt。 +7. `IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf V3_BUILD=/tmp/tianshan-xterm-final/build python3 tests/ws_subscriptions/verify_xterm_assets.py`:全部 vendor/gzip/许可证存在、字节一致、最终 www.bin 目录名存在;固定 SDK 重建 SPIFFS 与实际 www.bin 字节相同,容量及 flash 文件校验通过,见 build-assets.json。 +8. 相同 IDF_PATH/V3_BUILD 加 `V3_RESULTS=docs/repair/xterm-local python3 tests/ws_subscriptions/verify_project_assets.py`:原优化 JS 语法、gzip、缓存标识和 SPIFFS 重建验证通过,见 project-assets-check.txt、assets.json。 +9. `python3 tests/release/test_release.py`:3 项通过。静态检查现有 workflow 的 build/*.bin 上传与 firmware/**/*.bin Release 模式包含 www.bin。无 workflow 修改。 +10. `git diff --check` 通过;build-inputs.json 的生产输入哈希在构建后复核一致,无构建后生产输入改动。runtime-search.txt 记录 components/tools/tests 无可执行 xterm CDN 引用。 + +完整网络记录:源码 [英文](requests-en-US.json)、[中文](requests-zh-CN.json);优化产物 [英文](optimized/requests-en-US.json)、[中文](optimized/requests-zh-CN.json)。每条 HTTP/HTTPS URL/origin 均记录且断言同源,外部请求为零、pageerror 为零。vendor 请求带现有缓存标识。无 CDN fallback。 + +浏览器真实运行 xterm 及键盘;网络/设备 WebSocket 是受控替身。现有 resize 仅调用 fit,Ctrl+C 发送 ssh_input;未擅自新增 ssh_resize/ssh_signal。独立 resize/signal 控制路径由现有 C 跨层测试保留验证。 + +## 从产物到运行入口及发布链 + +最终 www.bin 由逐字节核验的 web_optimized 构建,含 vendor/raw/gzip/LICENSE。`ts_webui.c:static_file_handler` 去掉 query 后访问 /www 对应路径;`ts_http_send_file` 识别 JS/CSS,按 Accept-Encoding 发送 .gz。浏览器在源资源及实际优化资源上均仅请求本地路径并完成终端输入和 SSH 模式操作。真实 ESP HTTP 服务尚未执行。 + +[flasher_args.json](flasher_args.json) 的 flash_files 包含 `0x6a0000: www.bin`;CMake 现有 FLASH_IN_PROJECT 未改。**使用项目标准 idf.py flash 时,本地 xterm 随 www.bin 自动刷入设备,无需用户单独复制文件。单独刷 TianShanOS.bin 不会更新 xterm,因为 WebUI 位于独立 www 分区。** + +现有 OTA 的 includeWww/startWwwOta、ota.www.start、ota.www.start_sdcard 与 /ota/www 上传链支持配套升级 App + www;App-only OTA 不更新 WebUI,这是原语义。现有 workflow 继续发布 www.bin;本轮不修改工作流、打 tag、合并或创建 Release。 + +## 验收边界 + +本次必需的本地检查已执行。真实设备浏览器、SPIFFS 挂载/静态 HTTP/gzip、更新后的缓存与真实 SSH 仍待实机验收;未刷机、重启或执行真实远端命令。构建成功和模拟协议不代替设备验收。发布准备按用户授权仅提交并推送本轮范围到 PR #42。 diff --git a/docs/repair/xterm-local/assets-check.txt b/docs/repair/xterm-local/assets-check.txt new file mode 100644 index 0000000..9ca348c --- /dev/null +++ b/docs/repair/xterm-local/assets-check.txt @@ -0,0 +1,51 @@ +{ + "files": [ + { + "file": "vendor/xterm/xterm.min.js", + "raw": 283670, + "sha256": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "gzip": 65684 + }, + { + "file": "vendor/xterm/xterm.css", + "raw": 5383, + "sha256": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "gzip": 2037 + }, + { + "file": "vendor/xterm/fit.min.js", + "raw": 1789, + "sha256": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "gzip": 822 + }, + { + "file": "vendor/xterm/LICENSE-xterm", + "raw": 1261, + "sha256": "b569f629d00f2626a8100df2a1798210535621e42164dfd426a6fe5aac7b0ccd" + }, + { + "file": "vendor/xterm/LICENSE-fit", + "raw": 1103, + "sha256": "e256f01188af527e4d06d21d06fbf785ae9c50d4b328bf03cbe0ba7f0aa4228f" + } + ], + "runtime_raw": 290842, + "runtime_gzip": 68543, + "vendor_raw_including_licenses": 293206, + "spiffs": { + "partition_bytes": 3145728, + "allocated_blocks": 676, + "block_bytes": 4096, + "unallocated_blocks": 92, + "note": "generator allocated blocks including metadata, not runtime filesystem free-space API" + }, + "www_sha256": "8b7b51a11c281121fc80b7bdd6104fa4a522af39fb698902bf717faa710d7b4a", + "flash_files": { + "0x0": "bootloader/bootloader.bin", + "0x20000": "TianShanOS.bin", + "0x8000": "partition_table/partition-table.bin", + "0x16000": "ota_data_initial.bin", + "0x6a0000": "www.bin" + }, + "spiffs_reconstruction": "byte-identical" +} diff --git a/docs/repair/xterm-local/assets.json b/docs/repair/xterm-local/assets.json new file mode 100644 index 0000000..38404c5 --- /dev/null +++ b/docs/repair/xterm-local/assets.json @@ -0,0 +1,41 @@ +{ + "index.html": { + "source_sha256": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "optimized_sha256": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "gzip_sha256": "6fac126090696747186340f090a4591b79ba7d111164f42fb9fc0aba8305b448", + "optimized_bytes": 26676 + }, + "js/terminal.js": { + "source_sha256": "5d77a7181b6127699e098f22d3c872f5e31daaa700436b6fa928f34b6aa33e52", + "optimized_sha256": "6759587f527a0c37aaf8b13f6b5ffc017a452954cd23b780b5d6254488f939dc", + "gzip_sha256": "191a0dbe459d803d2a31cd01e041a339b3ebd571710cb48be243441b30f6c692", + "optimized_bytes": 20066 + }, + "js/lang/zh-CN.js": { + "source_sha256": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "optimized_sha256": "81b0fed5b0ac73d51d9c37204c9f62e035a79bbf5b5610d37fc8a936faf9fd64", + "gzip_sha256": "18581e4123c2466a2e3d7fa232f86330850606e02e75ab777d3542d3489b29c7", + "optimized_bytes": 137314 + }, + "js/lang/en-US.js": { + "source_sha256": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "optimized_sha256": "e9963046086616fecc9ba662df94e736a98c1430865e0caa47292b3690ca0ad0", + "gzip_sha256": "82e883f0a2a77ab09008dc4d2543b72e675749c2392c70cc175fabbba928bb54", + "optimized_bytes": 143161 + }, + "build": { + "TianShanOS.bin": { + "sha256": "9dc7abe01f06983ff6980095e90ec098ade716ea4bd1a67e9a94402e208270d8", + "bytes": 2183456 + }, + "www.bin": { + "sha256": "8b7b51a11c281121fc80b7bdd6104fa4a522af39fb698902bf717faa710d7b4a", + "bytes": 3145728 + }, + "TianShanOS.elf": { + "sha256": "9cbeca799ad830cb914e3af28d43debf4a7a1ba0bb39b16edcd1ed1bf7ada1f5", + "bytes": 18286808 + } + }, + "spiffs_regeneration": "byte-identical from verified optimized directory" +} \ No newline at end of file diff --git a/docs/repair/xterm-local/baseline.txt b/docs/repair/xterm-local/baseline.txt new file mode 100644 index 0000000..5138c94 --- /dev/null +++ b/docs/repair/xterm-local/baseline.txt @@ -0,0 +1,4 @@ +?? docs/runtime-repair/evidence/reviewer-fixes/diff-check.txt +?? output/ +?? tmp/ +633bb94df3e1e454929a14257c06c307c09100e6 diff --git a/docs/repair/xterm-local/browser.txt b/docs/repair/xterm-local/browser.txt new file mode 100644 index 0000000..b780996 --- /dev/null +++ b/docs/repair/xterm-local/browser.txt @@ -0,0 +1,56 @@ + +> test:browser +> cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs + +✔ zh-CN: real index cold start, safe toast/file text, current websocket state (636.478542ms) +✔ zh-CN: initial language failure blocks controls and retry recovers (281.836333ms) +✔ en-US: real index cold start, safe toast/file text, current websocket state (316.672833ms) +✔ en-US: initial language failure blocks controls and retry recovers (341.80025ms) +✔ delayed language package and rapid switches keep the latest requested language (246.9305ms) +✔ terminal resource failure presents retry; a rejected cached promise is not reused (384.200792ms) +✔ zh-CN: package confirmation treats names as text and applies only on explicit verified action (283.504042ms) +✔ en-US: package confirmation treats names as text and applies only on explicit verified action (321.021417ms) +✔ initial delayed language keeps controls inert until the real package arrives (241.532167ms) +✔ failed language switch preserves the loaded language; retry clears failure and stale toast (383.066834ms) +✔ terminal can initialize after failed resource load using newly served resources (384.491ms) +{"case":"successful retry","language":"zh-CN","failure":"/sdcard/a.tscfg: 应用失败: 设备处理请求时发生错误,请查看详细原因。\n详细原因:fixture failure","afterSuccess":"/sdcard/a.tscfg: 配置包已应用。","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure zh-CN (575.503083ms) +{"case":"late completion","language":"zh-CN","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: 正在应用配置...","errors":[]} +✔ review2: prior completion closes new package confirmation zh-CN (190.968958ms) +{"case":"stale file list","language":"zh-CN","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close zh-CN (198.094416ms) +{"case":"successful retry","language":"en-US","failure":"/sdcard/a.tscfg: Apply failed: The device encountered an error while processing the request. See the details below.\nDetails: fixture failure","afterSuccess":"/sdcard/a.tscfg: The configuration package was applied.","dialogClosed":true,"errors":[]} +✔ review2: successful retry retains old failure en-US (226.306833ms) +{"case":"late completion","language":"en-US","secondShown":true,"secondRemoved":false,"toast":"/sdcard/a.tscfg: Applying config...","errors":[]} +✔ review2: prior completion closes new package confirmation en-US (263.154417ms) +{"case":"stale file list","language":"en-US","callsBefore":1,"callsAfter":2,"visibleAfterUpload":true,"visibleAfterManualRefresh":true,"errors":[]} +✔ review2: uploaded file missing after dialog close en-US (238.29625ms) +✔ R1: endpoint-specific logout and HTTP errors zh-CN (190.351084ms) +✔ R3: late validation cannot revive an old apply entry zh-CN (183.495875ms) +✔ R3: previously opened confirmation loses validity on reupload zh-CN (179.444125ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts zh-CN (185.503708ms) +✔ R6: fixed upload destination and separate refresh failure zh-CN (210.39175ms) +✔ R6: out-of-order directory success and error do not replace latest list zh-CN (185.484625ms) +✔ R1: endpoint-specific logout and HTTP errors en-US (246.235333ms) +✔ R3: late validation cannot revive an old apply entry en-US (270.721917ms) +✔ R3: previously opened confirmation loses validity on reupload en-US (250.586958ms) +✔ R4/R5: obsolete errors and finally cannot update newer attempts en-US (225.006541ms) +✔ R6: fixed upload destination and separate refresh failure en-US (251.99725ms) +✔ R6: out-of-order directory success and error do not replace latest list en-US (250.931958ms) +✔ R2: authenticated startup initializes once (292.264208ms) +✔ R2: obsolete system loader cannot update new page; failed navigation retries (243.894583ms) +✔ R4/R5: newest result wins over late success and late failure (240.889917ms) +✔ R3: overlapping writes to one path cannot claim current verified content (238.512625ms) +✔ R2: disposed page only removes its dashboard callback (293.29875ms) +✔ R2: stale finally cannot unlock the new page read (244.392583ms) +✔ R1: delayed sign-out does not clear a newer sign-in (231.425458ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements zh-CN (313.898208ms) +✔ WS protocol: actual page subscription class, independent intervals and acknowledgements en-US (354.845959ms) +ℹ tests 38 +ℹ suites 0 +ℹ pass 38 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 7115.792375 diff --git a/docs/repair/xterm-local/build-assets.json b/docs/repair/xterm-local/build-assets.json new file mode 100644 index 0000000..9ca348c --- /dev/null +++ b/docs/repair/xterm-local/build-assets.json @@ -0,0 +1,51 @@ +{ + "files": [ + { + "file": "vendor/xterm/xterm.min.js", + "raw": 283670, + "sha256": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "gzip": 65684 + }, + { + "file": "vendor/xterm/xterm.css", + "raw": 5383, + "sha256": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "gzip": 2037 + }, + { + "file": "vendor/xterm/fit.min.js", + "raw": 1789, + "sha256": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "gzip": 822 + }, + { + "file": "vendor/xterm/LICENSE-xterm", + "raw": 1261, + "sha256": "b569f629d00f2626a8100df2a1798210535621e42164dfd426a6fe5aac7b0ccd" + }, + { + "file": "vendor/xterm/LICENSE-fit", + "raw": 1103, + "sha256": "e256f01188af527e4d06d21d06fbf785ae9c50d4b328bf03cbe0ba7f0aa4228f" + } + ], + "runtime_raw": 290842, + "runtime_gzip": 68543, + "vendor_raw_including_licenses": 293206, + "spiffs": { + "partition_bytes": 3145728, + "allocated_blocks": 676, + "block_bytes": 4096, + "unallocated_blocks": 92, + "note": "generator allocated blocks including metadata, not runtime filesystem free-space API" + }, + "www_sha256": "8b7b51a11c281121fc80b7bdd6104fa4a522af39fb698902bf717faa710d7b4a", + "flash_files": { + "0x0": "bootloader/bootloader.bin", + "0x20000": "TianShanOS.bin", + "0x8000": "partition_table/partition-table.bin", + "0x16000": "ota_data_initial.bin", + "0x6a0000": "www.bin" + }, + "spiffs_reconstruction": "byte-identical" +} diff --git a/docs/repair/xterm-local/build-inputs.json b/docs/repair/xterm-local/build-inputs.json new file mode 100644 index 0000000..ddccc00 --- /dev/null +++ b/docs/repair/xterm-local/build-inputs.json @@ -0,0 +1,821 @@ +{ + "CMakeLists.txt": "73a24128dd9cb60d9e980787b80ec9f32e3b9f0b873c83ef17ee8ee75152fecf", + "components/ch405labs_esp_libssh2/.gitmodules": "467fd072f917e5068f5b2a846127b7b82f386fb5b238156aedf38cce2631ab9f", + "components/ch405labs_esp_libssh2/CMakeLists.txt": "defbc67e892a2dc88a98689c81d71703c494df741da1281a971a32c19d71ffef", + "components/ch405labs_esp_libssh2/README.md": "d4baa8a5f5b154b4c4543c11f32300572b3acdebc26c613749be1cc5957b1679", + "components/ch405labs_esp_libssh2/libssh2/.editorconfig": "286f4ce9ddba0c0725cc4d37055e5988ac22c61c1b36bb6ee1a6a895d419f411", + "components/ch405labs_esp_libssh2/libssh2/.gitattribute": "50641866adaa8d562ba65baca87f2f3ce91f61ca40fc21753fe8f35d6013befc", + "components/ch405labs_esp_libssh2/libssh2/.github/ISSUE_TEMPLATE/bug_report.md": "bc14bd2401eb9dfb7a3d762adffd5e455817705f387800ea7b6c38c1f1408633", + "components/ch405labs_esp_libssh2/libssh2/.github/SECURITY.md": "e694a8bc825fde44c30c1bd56465a04872a901406bb83c83055d20bb592485d9", + "components/ch405labs_esp_libssh2/libssh2/.github/stale.yml": "25a2e801cd260d70243072d3e5506c511bd720f3f6ef9fd7fa007b7d1c7ea8e1", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/appveyor_docker.yml": "da1c0951a12c434f05836f1789f15961c6fcabc603e647430a05a34b0424a24b", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/appveyor_status.yml": "4c5246d62039581107a7d02ce6e6add044316c0b74c1539a6e14b184d50fc52a", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/ci.yml": "5fa3a7f5a9fa332495ea33881713679ff28330a367cc4323488a987a3125ea9d", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/cifuzz.yml": "84b5ae690289c4db4b8cdd1907e7a3d63c8df5c3cc1ddd2d43633df7821b2e5e", + "components/ch405labs_esp_libssh2/libssh2/.github/workflows/openssh_server.yml": "0cf892551ec733d936325e69d4a4384666fd61c0227c39bb74887d805b180cdb", + "components/ch405labs_esp_libssh2/libssh2/.gitignore": "6c7cfd1ecdb57b89fc5b0fadc59727fd6cd3ed803e448e5811b785e54acd1a6a", + "components/ch405labs_esp_libssh2/libssh2/.travis.yml": "0230a26255749c26837b5dc54c9811565a1f2092bca181db030255d0d857769f", + "components/ch405labs_esp_libssh2/libssh2/CMakeLists.txt": "2798ced9569334a34eee6fed8037cc69d5a3b6b3af6ccb8f27fac5f6b39dc4b7", + "components/ch405labs_esp_libssh2/libssh2/COPYING": "859e60d760a3446ecaf777339f1eef98c527aea40714384d24b882a83ffdd23a", + "components/ch405labs_esp_libssh2/libssh2/Makefile.OpenSSL.inc": "8e82af68b172ddccf94c65c1b4e38b69b3b7f027cc14a54b6d660c5f2bcd4de9", + "components/ch405labs_esp_libssh2/libssh2/Makefile.WinCNG.inc": "79243be1029a0df52a5e79b3dceb80ac462f2e735e25445e38852610bee62f34", + "components/ch405labs_esp_libssh2/libssh2/Makefile.am": "af1c3b9cc5b46c35fc5556a458b819ca320bfd2646ff13d2bbc3fa0bf21e658d", + "components/ch405labs_esp_libssh2/libssh2/Makefile.inc": "69ed9dd108033552385a3b6257f47d1cece33490fec25c14ef208b3b8f9c9273", + "components/ch405labs_esp_libssh2/libssh2/Makefile.libgcrypt.inc": "3d71dbe94c906d07c70eb8c7eae80fe5ae014565d7a9446bd39b659e91b73b71", + "components/ch405labs_esp_libssh2/libssh2/Makefile.mbedTLS.inc": "18bf8364aaef158a27b65be88ac1fd74af0cbd336930b6ce611b62dab77feebc", + "components/ch405labs_esp_libssh2/libssh2/Makefile.os400qc3.inc": "ac9b0e1731f7dfa20e3987e108a4c5896e6095638ec545c8f2ac64c35b63a455", + "components/ch405labs_esp_libssh2/libssh2/Makefile.wolfSSL.inc": "d6288360c49d5246ba3757304e2c4850d96651d7dfe2d2583a8bee2fe9313665", + "components/ch405labs_esp_libssh2/libssh2/NEWS": "9418b9c8dcafc633c2c16372b2b21ceb70a06243756af21eff173a4b379101d1", + "components/ch405labs_esp_libssh2/libssh2/NMakefile": "2d1cbda9bccd886de3c99dae77f09ac75a7f09f1834272b4a9154d2a0ae9a81a", + "components/ch405labs_esp_libssh2/libssh2/README": "41df43a8f24ec77082fc4c4609bd54b17e0a610e6bb319171ec1fd4d31a24d02", + "components/ch405labs_esp_libssh2/libssh2/README.md": "d7595097b84462de1f273ed1628315f47b23dfaff070af2bfb14f38e22ec13b8", + "components/ch405labs_esp_libssh2/libssh2/RELEASE-NOTES": "9a88e3e26281797ee09f09cd04e4bd753837b02366dcaf34885b800742bc862f", + "components/ch405labs_esp_libssh2/libssh2/acinclude.m4": "c461e884733a19f15b603aec9ac590218ec0fd93e34cd48b279e2f0af5dc70f3", + "components/ch405labs_esp_libssh2/libssh2/appveyor.yml": "984dffbbd4503ebd67359d660d51198c420dab745efef074fbae126aa3fa8492", + "components/ch405labs_esp_libssh2/libssh2/buildconf": "c2102a17b8f50f0d56d20639c05c70347a4e6ac5dcec351c6f851371e2a68a71", + "components/ch405labs_esp_libssh2/libssh2/ci/appveyor/docker-bridge.bat": "f72fdb40e7a9c3aa5c5fe5fd6a4a008463f1f3b991e0875f19eb5a9a2e8fa3cf", + "components/ch405labs_esp_libssh2/libssh2/ci/appveyor/docker-bridge.ps1": "e8947a221954fd55ac060300bf71b512869a087694f4116ad40ffcfa5ede8160", + "components/ch405labs_esp_libssh2/libssh2/ci/checksrc.pl": "879e805b57e2e86f6894a6a4e395daf1c1c048ee5984e109be74afc750782567", + "components/ch405labs_esp_libssh2/libssh2/ci/checksrc.sh": "a435be07f99eaac5b59f9cf68d88e3541c9fbed09177d0874078c22547edd5e9", + "components/ch405labs_esp_libssh2/libssh2/cmake/CheckFunctionExistsMayNeedLibrary.cmake": "60a8d1afe9a3b71cedb782ac6187a9a041d2792006a7eb3379bc42a9fcb95a4d", + "components/ch405labs_esp_libssh2/libssh2/cmake/CheckNonblockingSocketSupport.cmake": "443b9824a1d7f7cc0a9c1b740ca9824f82f73ac7f0294aa2c1e3192aa3cb5e0d", + "components/ch405labs_esp_libssh2/libssh2/cmake/CopyRuntimeDependencies.cmake": "5a146613512f467192e7917561b305e31d52a85b3f216d5e3c6ca6d2261e9b03", + "components/ch405labs_esp_libssh2/libssh2/cmake/FindLibgcrypt.cmake": "af65a3a8ea63eb935b1602b2b75c7c993558f9118e8c12cf9f2d4614977d8c53", + "components/ch405labs_esp_libssh2/libssh2/cmake/FindmbedTLS.cmake": "db4ad3046a838c325ff39f3f083a2de39c3bcde4c69670610ce27b23c758c50d", + "components/ch405labs_esp_libssh2/libssh2/cmake/SocketLibraries.cmake": "857615772ee6a1b79826eb18889def1a626296262db78def698286930e3c6cbf", + "components/ch405labs_esp_libssh2/libssh2/cmake/Toolchain-Linux-32.cmake": "fc7c2718c2e628fe28db38406fb57e9380d202dce8b4d615ef8b818984c37a32", + "components/ch405labs_esp_libssh2/libssh2/cmake/max_warnings.cmake": "1a14b62c40d327d69ad1531e3372523310e642779da33c3865e6fc67df46835b", + "components/ch405labs_esp_libssh2/libssh2/config.rpath": "aa48652ef1709d015f0e627eb5d18d1c198d81c29d5f89a81362512fcba72b01", + "components/ch405labs_esp_libssh2/libssh2/configure.ac": "37d7a8fe37f7c5a7329f289030d2dc0571aa759d285ddab0a5b16ca27b1462b4", + "components/ch405labs_esp_libssh2/libssh2/docs/.gitignore": "b523bfc0065b99350f41f5f745f0be7698b3f5be00251e6c1016a5b620edcc7c", + "components/ch405labs_esp_libssh2/libssh2/docs/AUTHORS": "12228e95c6b41c76d00b6ca8f2bf7bfb3372f3f32b6c62f34882530b9406f26d", + "components/ch405labs_esp_libssh2/libssh2/docs/BINDINGS": "c711b535a9462815d564995eb84b997261fb9a2db4ef82a8c9b3f926dd7498b2", + "components/ch405labs_esp_libssh2/libssh2/docs/CMakeLists.txt": "713fa1933cf53a12a7ccafea3e8d9187c35967159e7e460a775e91e8a7df2464", + "components/ch405labs_esp_libssh2/libssh2/docs/HACKING": "5d2563866dc4fcc8a4ab352676e3d64b918b75e0a73ce7776b9eef7e8949d3b0", + "components/ch405labs_esp_libssh2/libssh2/docs/HACKING-CRYPTO": "ce85a00c816a80b24fa998598bfecb58ed9ea389a368c15eacf2e27d56f1be25", + "components/ch405labs_esp_libssh2/libssh2/docs/INSTALL_AUTOTOOLS": "6ca4765ca5ca117514e41067ce05cc24504aa29eab9a76bb9cc1ecc87c3280b1", + "components/ch405labs_esp_libssh2/libssh2/docs/INSTALL_CMAKE.md": "266b25dbe613f02e4662467c23ad80bb42a35ef9d579933ddb2d7b1d038089d0", + "components/ch405labs_esp_libssh2/libssh2/docs/Makefile.am": "5e734a3e68bf57a13404770ace3e4595e0a6c215526d2942a5fba3ebf3109828", + "components/ch405labs_esp_libssh2/libssh2/docs/SECURITY.md": "4314c11322a9970bed60130a2e11a0eb79c9de719a7c7c2cb227356d9771ba2f", + "components/ch405labs_esp_libssh2/libssh2/docs/TODO": "e3a304f76129bdb90371439567dffe2a8841e3a5c326f71000490a11241bc9b0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_connect.3": "5fe15d3e781382a8e935048dd266a89e9c3b63800d4714ceec6c78c512e49f20", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_disconnect.3": "e2d1a3af99d888e310c6e22227e11b0a42f1d265451a9e13ac787fe0b8075426", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_free.3": "332b5fb986c013ba363bd18d5e39c01a047d79fb22acf673291f1e19b4d8292a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_get_identity.3": "acdccde633dda1740ba043fb3f2b3aed884923c74ff3e2ad2f01d5a6b87955f1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_get_identity_path.3": "148b43bc669d3300b3fbf09ae57050a15ce074c8730ecef78e97ee9309ea179f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_init.3": "09029ddc71d63085dd6ccf92062ce6e31f0d54a1eb40d06587713814ddb4ee5d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_list_identities.3": "a498d332ea55486eb1c234468a8cf3c1886eb6b98bdd527a1b44fd06683e7ea2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_set_identity_path.3": "b60fb7e972fc2b420ff0a7452ddbf12597dbc9cb075920da16ee9c0eef7f8425", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_agent_userauth.3": "d2119c63fa5bd1a05385bd176a1c8d2ee0139aebec92addd1601edc948f17855", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_banner_set.3": "1bd7a8bd59cb74d90cfed26c41701788afe7c0a667f686c5154cd0615d586422", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_base64_decode.3": "c48f88f5a6405738bc146161bf442e02c02073e0b9957f5d4bc3bd425bee82e1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_close.3": "e348d7548693066f863dde9a6c7dd21bf394aca51c1cae1c4999309eedfb4451", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_direct_tcpip.3": "3a67560c5846880066344d5581840a26a8509854fcf20fda79f9b2156e58757d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_direct_tcpip_ex.3": "5a7665c77afd8aa509c03d5059ece42adb912979e0fab608034e4554e3106439", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_eof.3": "7ad4590d1dfccf35bd2f7393e0d14b4247c3108ee2f48685b505c0dd9516e011", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_exec.3": "e7f79363e4fa61ce0c00f59e4e97cbc3101f55e2025b1156551aaf50c8522b87", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_flush.3": "fcaf2b8577ae6b8196313977d0686175a807fcccd3f3fce433028384da0f7bdd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_flush_ex.3": "33fb6e5de6afa0836e6439ea4c552ff4101a6f48bb73242f4868b181d40bc28f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_flush_stderr.3": "4f590d465d647b416c583c2b16693a3364e84da2400dfe7f9ffe1928577ca3ae", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_accept.3": "4f0621fe2a6aef5fefd50197974beb6e6c89dc41841b1d6052f885a773557ed8", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_cancel.3": "230ff1688acf2f4a7ac5d687ca46bd39458192a0662b3b8fa6edd8217c25117f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_listen.3": "fac440afa8233b6d3982b349d56c177ba9fec09464f1c5a5bf40ce32d600197d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_forward_listen_ex.3": "49c5374f3b5c56213fe9a43ef4592cd51097cd1c9017fcb3be97c94847e8efcf", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_free.3": "a7e649756ff4a20b0f5bb6bc9f4647ecaff885c8745e9c304cc697c2c677196b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_get_exit_signal.3": "89557c3203331e1d21773b557659a0f21e1ecbcee90c372de3b6e159c7b78a7d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_get_exit_status.3": "d374651f3f72f3f179c37b4a44b815a1bdd998f803a121fc8bc5544c397224c8", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_handle_extended_data.3": "c8ba2c032cd2cd8fc5877845df624712457dcf1c092975f3c713fe75794fd42b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_handle_extended_data2.3": "17269accf920a28af6bd14770f94067083e2dfa56df4e08663844d0cebb78052", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_ignore_extended_data.3": "c00c30e1aa01c699c92c30c98e9ab8e543cb2fb23376b650627c56ecc3a1f275", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_open_ex.3": "a4153c3de3d2cb9a2faaa39eeb9b638c829db2cf4aa4a0e0a2cbd51098626e79", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_open_session.3": "63ee8e3220149933ebf5219335cf5b9fb107e23808137f782e8846b191ecf629", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_process_startup.3": "1023352b8152e5a1a2ccf2bc899e9539fbecaa2dff69ebb68ada088da38fc6b9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_read.3": "1ddb492b078cab328e718563f2fc5dc3fd737078ba272d078f94e554e2938080", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_read_ex.3": "931e1fad6ff1d629ed2b523c75e645a16344be8afebc0e2f50144ac8394146e2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_read_stderr.3": "6b3a6db85f2fdb26a07b95d6046127f3d5c709e6ee4bd72d66b9109e10ca8e1b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_receive_window_adjust.3": "01a3e1d79fce062cba8fefee6b8fe7ca81a1ad7a3c8cccf12801d7f80fd6265a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_receive_window_adjust2.3": "451f2632b8c786a16e87940f2fcb978e9d88fee27cb997c192c9e671b72b27eb", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_auth_agent.3": "9217dcc14a2c6bee93f5754b2fed7827b3dbb8efc335d7fbf4908e8a531570b4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty.3": "f7b4d6780a1b6ed5518e425751f55d9930a5bfa8e92dc0458ccdb06d7786ecbe", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty_ex.3": "ab2af9c02a3d127ba99cf27f0496643eb30810edb38a94f7df488f41041ec105", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty_size.3": "5ae6ade5d71da8ce3a31fd804c32600f54a3385b07cb8ed6ac90157a9a1ada26", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_request_pty_size_ex.3": "4b296b3a64b71c1842c0f12c70fe866734bc18f51e3907acfa3f04c4a997bda3", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_send_eof.3": "a83be7ac2b428f6d41df423e38c52d01f86b9fcafde2010336c7a57323808b6c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_set_blocking.3": "767637f9629f9b7bbbe24c3f3e13be0a83174f1542a63fe7daba350beb369447", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_setenv.3": "fc8773714c44358cf215d80dfdfeea082cc84ae0f33575d17a7825ffb785b02d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_setenv_ex.3": "d4641d1a3054af1fb1aa4819de5ce002b434e56745118d843adc70d902505447", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_shell.3": "e2986078e39068dd61d6d3df0d9e54adb0a489e55ba8051ae6ce3ad5f3c2c191", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_subsystem.3": "16e48c8ad515baef23e1ea94895cf0d2c6d397c133adcbbd20300304b64cab4a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_wait_closed.3": "8f7ad8093832b4b343b04eefe492e94a18be6f496e2074037f93b99683296663", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_wait_eof.3": "a96b063c1d90129420db176063ea4cb66f1b913a2d2b5ada2f3364eeda2d6543", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_read.3": "085331a4fb18dd396b016629ad241a7bf03afe78b0a09fec701aa8be526fab2b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_read_ex.3": "9faf5e32cc4e1fe69fa2e57dc31cbdf3f0e7bfcea339f3b7196f535bbe6be2e2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_write.3": "6daa6fd8d4f74957c709695bd74a741e7808e057cda1a0954e76f92f793d61c4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_window_write_ex.3": "052d12745f7a8a634ba0b3b36cf0a592c2425caf0679aaaca4776b664bd2d5c0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_write.3": "30bfc0efb86bf513f721200a89c9139687d58483826924b9b401797de74b6387", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_write_ex.3": "da8e46fcba16a2bca466d1397d8b06f03703c4cb7e7b799d582941e125c999b1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_write_stderr.3": "e15a48affe5a5044a2b70bf6fc1e3c6a1dc61c10c4440db4828080fe55e5a0f2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_x11_req.3": "e10544721e6dae96d4542abe07b43767ae6fff49a5bc87381aaf72be7d45f51c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_channel_x11_req_ex.3": "ece17b293092b2319ea237a2855a4b9b7c89c6954ecfedbd837d3d02ce4d7a13", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_crypto_engine.3": "da0d23d0aaf5762db26587138ea9db2bd87eda7f00b326d459424f875bca01d6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_exit.3": "104af206d55e98ffa72ae0c5a505523220c8d6e1de27a37a5139093476d5ede5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_free.3": "8abbc67b852f9fabe09eb84540b610304d896721a04a4bee1e9d0e8f8f08c999", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_hostkey_hash.3": "82070c7634690b4bddc49f3c83b343c6f792c902e0e48247d055eaf3284f80e6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_init.3": "926b4044a52cf71dac8ac23cdf51d6e76bc92f5a3a72c65371549e18826c1cc7", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_keepalive_config.3": "7ebbb7cdc900d6d6188afc537c05c60a115030609d96571ac447ac396991adc0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_keepalive_send.3": "86ac214dd4c086239d59ac6582926f72544c788ad2fbf3ccc4e678b4109d32a4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_add.3": "29a052f853cd3f19efc12612d4e3224271bdc91b10cf6b73e866d7018d25f07b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_addc.3": "c5a2b8510dc1df43311f17073e7e720232f7a7e25d9ba7ae80efe2f26a133297", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_check.3": "2059d72130dc5b99c6faa8b399166a8495cf02b71313d6648778b11b0adab631", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_checkp.3": "88cac561cc381008f64d4c879bbe626afd669090648441c134cae83a5ea082a9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_del.3": "34fbfa29546d2bf0edc380270937658f818d2600e4bdc658d5ce28c7d255e1ef", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_free.3": "3e319da43cb185d73dc215a75351f330de2194608a1b12b8e0b623c900d4d96e", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_get.3": "fc04784b136786dafb210e018e758d5272c8d9d531c4fc5baac9f7b90f65bfd2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_init.3": "509721c49287e0232b3cfeb41a8d4b44a45a195222a5694baf9d728c77225abc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_readfile.3": "6d72d5be2d5dd56b125c1107632c58d5e8a692871182f3f883f5662f39d7dfff", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_readline.3": "e259eaedbe587c06a74ada7c1cf5bf28a168edfff2a60919985aa6c7a15e56f1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_writefile.3": "5ef6daaf96128c0b756c9faf38b5fd60697fa93504a5cb9ce7139a3dc14f7254", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_knownhost_writeline.3": "32c23d5b4393297935c3fa6e03d57a3bc1d904e5e469cf775bb0516f9f885147", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_poll.3": "c4a377bc2be1c2789de7a57fa42baa51cfbb0bf4121153ee9cd5201507a8c2b0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_poll_channel_read.3": "5b3df35e57c3252fc63e819c69cc6405bdfd14c546b5cfc2a521563bcc9cb420", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_add.3": "2e7c2772fb78b750b5aa94c7bd38c100e52493f6fb050762af924e26ab2605dd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_add_ex.3": "76e23274e8b4756b03359b0fb5bcd05becba4cca1212ae2c164a32c2f10ee50f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_init.3": "5643aa57554f8daacbbff9e539c68cd1093172bd86d859109e6446ccc91a85d4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_list_fetch.3": "975705aa9fc187961fbab91751a5f41412a30d73d65bfe54862285061afc6c29", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_list_free.3": "5eba2104f91fb101014441df437c695b9b0b1e106b6268d623f886de6c237503", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_remove.3": "69423e4d9d6b76388f6160eb473e82449700569d449911163609c8b1c629ed43", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_remove_ex.3": "5c1632ac1685361577a4ddfd1f6257ecfc012225e1e8c2b126f93add0b5b6190", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_publickey_shutdown.3": "b152e6c493896da374b7b93468b23d7012e6232db06c331c158f9057b8053994", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_recv.3": "e3af95d4147fb29a893ee80c8af430b7df1d77048d814c5005243c02fe221e18", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_recv2.3": "9fc689585ec209d13e5a7c5db6750e07b171103bd29d3522424f6d812473b95e", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_send.3": "0b72a5932217f8e561840de2ce3e5077bb40e7631b1dfb6f439d4a2413f83cfd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_send64.3": "3225083c74987af71d4a2947a7852ac810fd87ab12532492f286d7e7d7547456", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_scp_send_ex.3": "07818e45119b15208123655f945e1927c0971d21ae6d410fd26944b86cd41745", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_abstract.3": "56b29e317d2676d842f3854d8ffd89723a40992897b962d9ae07b56b2373a727", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_banner_get.3": "78804fe78c70c1fcc408a493564c989f3d3da36bf56d14344df150bfc65570c5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_banner_set.3": "c058557ca5d9633b560e05492212b52ee3f6477dae79f75c8ab4996828d88f09", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_block_directions.3": "0006e5c9788d8b2c3976274b715ab712fedb6ee4d3caa09071b62b846b7d44ed", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_callback_set.3": "6c33ad4047e740e5d020ba14cc5ce06beb0bf02b4b2f88c1ab7fd79e6e5f1b8b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_disconnect.3": "382845fee521c18828a9611c286919218fe51a4a3185f37f5c6e8a10a081db66", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_disconnect_ex.3": "5ed79115477f25aa8cf5998bf46eadc2383fd6e4eacee32622d961d4080ffa11", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_flag.3": "18317502888f1b7da8ef132500e009c8eed72cec5ddffbeda575a4c5093d8b74", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_free.3": "7fd404b4fb4c5e955cb2b8fee9b72a89864351e63c553e56a80dfc2af8bf200b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_get_blocking.3": "947a5fe43a518c13ba5049d820084ec6eede2bc3687923e67b28a75297431378", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_get_timeout.3": "4e808b2407358466171f2546c5220def1db4460a16d1f24c60a4a5186d6c0606", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_handshake.3": "fcb9fc145dc6f3b29871dcbe9c3d27529790e1cd3e20643c8aacb3d3d628fb5b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_hostkey.3": "0df40e6f599dacefcebf30b19331e4ce0abfad5bce75f5cffc8f4b7947bca5c6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_init.3": "ce1a0e9ecc5a17d607437b01f4ee94d5a0d8c5dbc8a04f1e26d3b74daedae57a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_init_ex.3": "2c169699aedd0f9ca16fb71a90618738dcdfa5b2b70d857a39c60896ba62b86b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_last_errno.3": "fe92e9c94ecb5fa33bbf51f866bb62bc4a1e5c3ea153dbaf34aa6553cd477ebf", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_last_error.3": "b14e30dc25d7daaf46ef119176af947efabfad29eff7f726635f2adb6260e97a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_method_pref.3": "6946c31e6d51b612852bed10d4ea869093a048f6d41131addbcb9c4dbbd767e5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_methods.3": "d8c8dccb3183da86943815b18ce7c903e07b02714d6ed8c27dfb782f852de8df", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_set_blocking.3": "33c01981b30ead73c614fcb6f7f224a39d6e849e6a9bccc9b8dd463719e1a39d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_set_last_error.3": "147c7ad527163e73f3fe285d16c980de60bba09813535a7623a1e0a037cfd1cd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_set_timeout.3": "eae71fab2f62942d4e5b66d93a7f49347a08ad1afdfc9a81ce8fcc0d0a9b0068", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_startup.3": "425118593ad0eaf0688c686d9b75f12b7cdb23d330445077907c6e2023cfef77", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_session_supported_algs.3": "a2fe37982e0f274bcaeea77ad33ca8fa06ea9377aa4e8196c3a8a827e2906b74", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_close.3": "95f03395996cb7b2652cab241a7d91d0c57bec6d4d8f8097b2932acb56eb7bff", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_close_handle.3": "c813fa985be5105cc3cacaf23dc01f0442628c005e629115992a280597301368", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_closedir.3": "1230d8cc661c016991f32b757b11ee6ddd1ac551e5522c5e009f21ef624dfdc4", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fsetstat.3": "a7ab72ebfca8d295a2b48f2c14d831568042ef6a0528e590faa99f5e2dd00675", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fstat.3": "e354ea4b96d512a34db42be2eaaa2c7fb0bfed554e726aa79db7f45ade1f9dd1", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fstat_ex.3": "2446ac64b425dbaf115b37d29107b66fc0291c2ebd17898669c406a4fd57b78b", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fstatvfs.3": "a10a9bf1dda75b0e97966ed003d183728a8ded895eece58e458980bc742f7a39", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_fsync.3": "bee468765b5d4a09a3b473eba0cf436328f29806953bc1f998d8bc97d2a3049f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_get_channel.3": "90e527f9eb6b0d17760328f6e3842f74d1d173fe88a7c9ec2357ca471e9c0f41", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_init.3": "585d782936f71157d141474c94c897d7ea292580445550c25c8fd44f5e03052f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_last_error.3": "8e7b2fa2c5fe4792a39a5c1c24baf041c970e3021511b36e59979ed64a18b4c7", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_lstat.3": "a01353b26374401029f5094a24beca08988ea201ca2197fef2b14f30bb2658e5", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_mkdir.3": "14e04b070a6c351e2af6bd68f73a408e2982e9a358d5d2af5a46d8b422d27ce3", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_mkdir_ex.3": "44c17758d2b0336f94c4004bdd2debf9e1632ba12c6db6df495c09a71a58e59f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_open.3": "af9a8c90999412d3371218f59859ff91c6a83eabee75f1712adf94c5bceaf1d6", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_open_ex.3": "11661fbcec142d9afee722f5ce779bd32f6e0a2b2dc45558c3bd47292105231d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_opendir.3": "62639f60918835e08f3c00d708cb32af319b9a56d3c2cb33ad409b60b347b31d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_read.3": "1d0435c740470b8a6a427da4331b576833eead72f9d976001d8a1f55fcf24815", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_readdir.3": "0e98293f67ae019adf8c5e17fa9f31f3e34b082c55ccd2119ee424f30c337fc7", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_readdir_ex.3": "7f9a2bda1d49d12040796015a842b592decfb076230ee9c8260c31e7b12dd2cc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_readlink.3": "1834815d254c351664cacf38c06a4b232f099787cc09a41ef719a1ff242e4064", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_realpath.3": "6b8e75bf89724998c414487d93f8c4899a3b1f4deba50806a798fdf9f9405bab", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rename.3": "eb87a9b1c94f38913c0cb62a3a474fe8c8f3cb0a874c61ced396a2d8bb92e510", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rename_ex.3": "12d2e70027755937df6de8b0836f75509f4fc5f1a5428fe5a92ae3eb23ff4b54", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rewind.3": "4caf86de2f35e2925ee637a68f7cfc2e76dab54571ada06495a0574e549c6a7c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rmdir.3": "86a1935b7bb291041eaa7c0788f417c6398b39fd208b6bb478329299ae72a49f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_rmdir_ex.3": "17029aa15ef3e1c862731a7ee52e8f730dc8951e62e1c0539b922dbcd66810b0", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_seek.3": "546a134db735df610032fa982d3c8c1013ced779e21faeff261d71041bcde8bc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_seek64.3": "07df7a2c8c9d75b198fa60909baa31e1c883002337a4c6b7a1b3a9c6ceb3a594", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_setstat.3": "39c7f5d489ea5ceb51bd9c7de237464f5c510f3ce0983e57f7b69207ef957e01", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_shutdown.3": "48bf057f1836924e3e5009890cb6e63ec9d11d0aa19abc258c75ee7c7bd097b9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_stat.3": "7fa4495645b580c216ca2279168b6b2f7c9c73a973dabf1997c02a0409d8c042", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_stat_ex.3": "fd19ff075f44a1713d765330d069fd63cffd8b2dbc09ce9170d926f25d5f70c3", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_statvfs.3": "5762f9ff7d56f44164db57fd048daa60173794c4e7a58ab2fb255e29f0ca2bb8", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_symlink.3": "ae7ea167057c307552405124ad54ee488db7354e7caa974334e88f5b2104c88a", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_symlink_ex.3": "7e22a39bb97548428cddc8a9cf3bc7a1ff57cde878b337a7e177730bf5c51d01", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_tell.3": "ce22525601570f33d91469170d43470a8a9decf0b35ae82c2cea72fff1dc8d8f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_tell64.3": "db5faf0fd28de4738e3062555c1d6981c2b272d7b89bd85e3e83d2a03237472f", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_unlink.3": "d8c4c60c41e81149fe14a4a00cc114d3f7bb4799ceea4895c67d79363da3ae7c", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_unlink_ex.3": "64b0723444b716d2b809a3b481024523fc8c62ab45d3ec4274040abf824cf611", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sftp_write.3": "a4706e9d6dabcde2aeccba27f7d7d5a3cef33dd21f4bf66bf5b181c3e8a3f9ef", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_sign_sk.3": "7d35515c97ed9fcb5c6a43da9f3fc4feb1c5fabd64cceeca0a790bd0df955b28", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_trace.3": "636417e1798bce85c2058cad56493919c608d426acaac409ec1a489bdef90fe2", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_trace_sethandler.3": "b37355eff49dacc9916818db61258f21665fb68993e57ca9040db056453bf8bd", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_authenticated.3": "81115e3ac2549eadafc5ab8c73462d1c5565593106c4d995a920f718e5dd451e", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_banner.3": "1a7248076b5f48794ff638a3f44e88e297548d8e664b792fd6ec3ff9c5017c09", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_hostbased_fromfile.3": "265670d504f8db399e9253af673264b92ae8cc3593912e9b2e6aee436d02fdfe", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_hostbased_fromfile_ex.3": "a71631a3eb07ac88ee21beeabaf6aaccb7e93378c98eed228fa27f1575b04a64", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_keyboard_interactive.3": "17d55c3ba83fc9b7a2fa1dbf0e0d1886deb87616298b6bf424b5ac7d63d0da39", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_keyboard_interactive_ex.3": "09774448b68977b58a745775d5f568077960a9da178f5a2e570359e16b327354", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_list.3": "af6928a269c96480a6ea3a3452af7029577f69485fee36ecdd9dde48b4956a5d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_password.3": "4c8103bb95903b0b2ee6c2b1d0b3eac150ab31314ec023424ab564d29b1678a9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_password_ex.3": "0834a29c814a2d617369a2463429ec244fd116bce0abe8f1b6e61aaef35db3eb", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey.3": "874ece028410feb1bb33d481ab2789e6fadc9a9974cf4e0a72517b4c3fb81861", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_fromfile.3": "6864fc6411955179866986cf95f75ff41a022a4b60ceb177cf503da45a67b88d", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_fromfile_ex.3": "060d36d8a06538035e0d7c678f78db16d68ad6f930c958ef3c1bd46f96f9ed39", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_frommemory.3": "5022660ab3c6c7f596b92e887debb3c580dc21f64be71b76c83c033c0fe36ef9", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_userauth_publickey_sk.3": "5c779cca1464db0aebd956fc3fce989c0637e6e91dce4114991b457e2cb616dc", + "components/ch405labs_esp_libssh2/libssh2/docs/libssh2_version.3": "d3feeb9f870be0dacc7616c44dffae9abddcd22eec9cc8c18a0526af723ffce8", + "components/ch405labs_esp_libssh2/libssh2/docs/template.3": "740b501cbdd74773bdb93c8a4d1ae1e175f3593c0eb93844ea2cad0c61e14463", + "components/ch405labs_esp_libssh2/libssh2/example/.gitignore": "519ee26ed4fcf44a7ba26c65a50f13b343da0a0da55f14f94889b902a3a61939", + "components/ch405labs_esp_libssh2/libssh2/example/CMakeLists.txt": "f8cc011f16f189f485ed9060d71de862616c254dcfc1fafe49ff6425a4d89757", + "components/ch405labs_esp_libssh2/libssh2/example/Makefile.am": "0e7c6f2ea9a65a6eb253d721cabc8df573cd4d2606ddc7bd7499b701380157a6", + "components/ch405labs_esp_libssh2/libssh2/example/direct_tcpip.c": "1a335122f9e28b3883587768e8332f3883b462def477f8651b83fc1392e96dca", + "components/ch405labs_esp_libssh2/libssh2/example/libssh2_config_cmake.h.in": "115c1b79ea918a83de959f0f50eb98c2ce252b21b566b9ad56f3c23b68e48ae7", + "components/ch405labs_esp_libssh2/libssh2/example/scp.c": "87736832ddc36e80b52ed6b7f1c87eedcb57d739c80dcff5bbf2d610bfc7f7c4", + "components/ch405labs_esp_libssh2/libssh2/example/scp_nonblock.c": "dfa78c57e18acdb437f3a643dbace70802aa7d2d504adcd47ed63f744189e822", + "components/ch405labs_esp_libssh2/libssh2/example/scp_write.c": "3a3c4dfb3c4688558716a364cf0f4d8b767bf30c59cc6b352394a2d698370930", + "components/ch405labs_esp_libssh2/libssh2/example/scp_write_nonblock.c": "8071bf056b72eee39bbb1ee173193a79e6ac8a2812724b3e31bb919c6b8ba370", + "components/ch405labs_esp_libssh2/libssh2/example/sftp.c": "6a0bcb5ec7b3066cd040bfc29243fcb36f8375575db17415974a20c29892f6b8", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_RW_nonblock.c": "a2eac2e5433d8e63fd416dd8d0b1424536b4dae701360bf9ec3024495d8c6eb9", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_append.c": "e9aa3ad34d7c9aa119a841e16e99657aa28596b184ff38d09df3a1319dfbf9bd", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_mkdir.c": "51f94316a6fc8ce1c6de9bff0599fa95a950a1424e94b676410d76b1e1edc879", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_mkdir_nonblock.c": "0fb08ab3d217af555d7512693a56c63094642247054def280cbcb08e2a3612c4", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_nonblock.c": "c7236ccc7897e1abd3d9176a33cbd059327d30fc95c7803f7e5f99bf3c448a3f", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_write.c": "7e972aa778422c962ba0ebd2fbae109865b334e33c371ae94a8634e74ffd5473", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_write_nonblock.c": "6b18c9371c2ed1e22b005232f80b99959cc68f2e0dc1351fa73d678e7c64a329", + "components/ch405labs_esp_libssh2/libssh2/example/sftp_write_sliding.c": "b88419136786cd31709d9466b0e4a131b990bbd425096276e5699559863d4bd7", + "components/ch405labs_esp_libssh2/libssh2/example/sftpdir.c": "d186de774a29db36a87fe2f66011acb5c5847316791c98f39dc2749a4c448209", + "components/ch405labs_esp_libssh2/libssh2/example/sftpdir_nonblock.c": "6282ae10e701e48063a793ab2e7a819be77f7267dd7ec29264339c41c5dad8ab", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2.c": "2789139110316e87a06b4d6132fb86081c545084358a3ddf6bb5128423eaed49", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_agent.c": "3184d5a396a9067279ec16070c699a8baffdc02c70930f8cbecbd1cbbd489d84", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_agent_forwarding.c": "2db3d78ce1c5bdb2453f7d22cdff09cf1dc3e40aceb8a54faffe6f76af88d1c3", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_echo.c": "91c519486541145f579c550fddb5ffde5933ba0aaf22366ee8aec50c0cfe4933", + "components/ch405labs_esp_libssh2/libssh2/example/ssh2_exec.c": "67afd0ef23627c87eef2e4424967eef26f8154ce50c357cad85f7d3764fcd5b9", + "components/ch405labs_esp_libssh2/libssh2/example/subsystem_netconf.c": "9b076de4366e11ca81e88d60f6dc41ff3ad897d3096f148ce4ce00102d7256b0", + "components/ch405labs_esp_libssh2/libssh2/example/tcpip-forward.c": "0a929eec2a7274e7592ded5f63230de45c1f30578ce92ea14a010a33b231ac42", + "components/ch405labs_esp_libssh2/libssh2/example/x11.c": "310b0aef741a513db213a895fbf772076e35c2ee83eb4ad1f300493ef6b5b436", + "components/ch405labs_esp_libssh2/libssh2/get_ver.awk": "ac9314659d618e57f0d57e9cb2dc5ab14ca342f099de6738e93d58b91f698f14", + "components/ch405labs_esp_libssh2/libssh2/git2news.pl": "26cad7a3870941f21348bfdffd05fff7a1e1c650b8e38fe469bab3a2a221f26c", + "components/ch405labs_esp_libssh2/libssh2/include/libssh2.h": "2d36bee9e1f99a333cd21c489f649f574fb1c615165da1cd2fa50f5186315f64", + "components/ch405labs_esp_libssh2/libssh2/include/libssh2_publickey.h": "2d419bdfbc155cec62cc23d7cb87f3d9361c4f26ce3b3910c74cef715bd2e70b", + "components/ch405labs_esp_libssh2/libssh2/include/libssh2_sftp.h": "8a0c63c323edc42286cc608f9a53cebe46ac91432e1080a8520ab69d3caeadbf", + "components/ch405labs_esp_libssh2/libssh2/libssh2-style.el": "14bd86ae83b499f88b47f57cee18f1a7f4f41650e16e34af4b8ff03970c3c059", + "components/ch405labs_esp_libssh2/libssh2/libssh2.pc.in": "a2c375f048235970c995e4a091fca2cb500574151c356f7682d44deeb90623a0", + "components/ch405labs_esp_libssh2/libssh2/m4/.gitignore": "b96df5710e539dde8424e3c38174598386aeaff62e4b4a3a878a3f8290a7f9fe", + "components/ch405labs_esp_libssh2/libssh2/m4/autobuild.m4": "37dfd034b5ea52bede69c54901b818a461ae73e2ab1e28c61c229a87f24a1817", + "components/ch405labs_esp_libssh2/libssh2/m4/lib-ld.m4": "18c4c458009da32c9daf0ea332a539e5edc82ba009b6c2faac004626313f00e5", + "components/ch405labs_esp_libssh2/libssh2/m4/lib-link.m4": "d7aab3772e5b60d3ec57ae8dc66d9b762f5c68ef1e8516df25fadfa8bdfef379", + "components/ch405labs_esp_libssh2/libssh2/m4/lib-prefix.m4": "4797426d11dad1e5e4fdbc8bcbc8b10d9750f47bcb74e4c07a953a15265e902c", + "components/ch405labs_esp_libssh2/libssh2/maketgz": "a4ef1a17c664f3bf350ca4357219a6df4af7d0b27c4588fccf5f1e630f54d2dc", + "components/ch405labs_esp_libssh2/libssh2/nw/GNUmakefile": "d6afc1888b0fdfcb50b29a3d7080a4183de41a444c7063db93a1b56d533d8dd8", + "components/ch405labs_esp_libssh2/libssh2/nw/keepscreen.c": "f95e6f4851f16bde13e51a1f4f6f405a142c6a7940beda74de8058db2f170ef6", + "components/ch405labs_esp_libssh2/libssh2/nw/nwlib.c": "d81b0ad6d05938507ebc3c0510021e889a2d68a74d50709df981d2339798eb78", + "components/ch405labs_esp_libssh2/libssh2/nw/test/GNUmakefile": "fb00a4a6776f14c1789ac8abc0b0136b79813177221355fbd3c5b1907da938e2", + "components/ch405labs_esp_libssh2/libssh2/os400/README400": "f5ce6d4f86e2334f5c271020195fb0964083e19e2f44dea4c4d62e7a9bc9f4da", + "components/ch405labs_esp_libssh2/libssh2/os400/ccsid.c": "07d12155f5b9b2be9e5477fc2818a7e98183eedc247370de04d718eef506fdb8", + "components/ch405labs_esp_libssh2/libssh2/os400/include/alloca.h": "f2b4c60ed1f78832b9141cb64e5d1d8e187d90afcb5f9f1d56dcf3f9e185d236", + "components/ch405labs_esp_libssh2/libssh2/os400/include/stdio.h": "ce35104d75377458c0c38aded5375141abf22e71215ef7533a482ceec279c731", + "components/ch405labs_esp_libssh2/libssh2/os400/include/sys/socket.h": "05599c77ea5f79337a77e7b24f4d63f40b929884141fbb66f356d825c09c8dfb", + "components/ch405labs_esp_libssh2/libssh2/os400/initscript.sh": "b27631198e5eea8048684f8fae95ef27eef1f712742265022bf4eb1ebfe589cd", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2_ccsid.h": "13a0b3c9165d7ef27ce242c64ae191f876a1fdd65f0b4d768cc3235c2509910d", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2_config.h": "313f35a0e84d1474dbdb3173585e53c417956a8f92365a75d5ae53faf179345e", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2.rpgle.in": "0ce3e5bb7c33bb6dcf960af6267b4c0e3cc16259ae881724624c9fafbcc090e6", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2_ccsid.rpgle.in": "439d9e4c68c9b20a618e305e51f54f817a9cc51dd37b62f5792232048ed3ff80", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2_publickey.rpgle": "b138035c36feb1816c6a99b1d98daff7997b05d02325cad1d9909f983e4a330e", + "components/ch405labs_esp_libssh2/libssh2/os400/libssh2rpg/libssh2_sftp.rpgle": "7d6fcfc290b07c8bafbbdfcf61e19456ab6961afe23a0aa142110052a33e7ace", + "components/ch405labs_esp_libssh2/libssh2/os400/macros.h": "38360f3613c00f49178996cf53d2519009a0b3fab161db7aebff143149730c5a", + "components/ch405labs_esp_libssh2/libssh2/os400/make-include.sh": "c75efa9eba5bcaa1e75f60110dd463c2c6866b486186db705d49518c1b0fd8cf", + "components/ch405labs_esp_libssh2/libssh2/os400/make-rpg.sh": "41cce97d1dec97571160c98967db4ab27af9c7890cf4f7aa238b3d6b6aa69eee", + "components/ch405labs_esp_libssh2/libssh2/os400/make-src.sh": "c750bd85a5153b10c61c069a7d1ec253ec3587554f2da60a144dc4246ff50e67", + "components/ch405labs_esp_libssh2/libssh2/os400/make.sh": "07f221c0d6a9e7b1c55e5d1cc8e3babe7edb6b4bad3063827b55265bec9456e4", + "components/ch405labs_esp_libssh2/libssh2/os400/os400sys.c": "2c9bc9de576376b0a37c401c64b59990e2f74ceafdb0a8c6555fb8de5be2b01a", + "components/ch405labs_esp_libssh2/libssh2/src/.gitignore": "b9193860f4137ca619b15f6f76ecbbf8df6210fc9a5ef2d53c856279e2b848fd", + "components/ch405labs_esp_libssh2/libssh2/src/CMakeLists.txt": "00462a0ce4e94446ee6c32616518db7f0539b90980d4d4a2929c295ff9dc8ece", + "components/ch405labs_esp_libssh2/libssh2/src/Makefile.am": "655563161c47286f17fd9d992f15115630e3910828e838f11759bd70bdc91357", + "components/ch405labs_esp_libssh2/libssh2/src/NMakefile": "bad4819608f02f282aae84462a7c3f1d1b199ee0fc86abdc9ab7326ee6482576", + "components/ch405labs_esp_libssh2/libssh2/src/agent.c": "29c2a52cba4eeac57ed9a3808cdefbc4e9e07f269152dddcc7038896eacce424", + "components/ch405labs_esp_libssh2/libssh2/src/agent.h": "1348e28650ce7f4350e4e1b92e26d7c45e729fe3b9cd68db716e40a64ea15269", + "components/ch405labs_esp_libssh2/libssh2/src/agent_win.c": "1c8d67a82e21c539c62f3a0b4c715fba81ca40cee588588d5e4f1abb389966b1", + "components/ch405labs_esp_libssh2/libssh2/src/bcrypt_pbkdf.c": "604344b6447e2da31608c00e432b3cb62cdbf11f25c6ba3c64f539a9f771436c", + "components/ch405labs_esp_libssh2/libssh2/src/blf.h": "b54edc453639a810289315bc3d4de37bc67bd0537260e1df7f8f21f5f1c36c6b", + "components/ch405labs_esp_libssh2/libssh2/src/blowfish.c": "23d5952bb059823ad3a3174d641655135991a9e849fadd00634516b977cbc17a", + "components/ch405labs_esp_libssh2/libssh2/src/channel.c": "0d23d9583e2f14c8f660d614ce16e8f48a41421434db588f19a953ad100ac3dc", + "components/ch405labs_esp_libssh2/libssh2/src/channel.h": "3be8e8b444461111fe0d35b21137ffcd4f681c1357616e0db4908bd434e97bbc", + "components/ch405labs_esp_libssh2/libssh2/src/comp.c": "0fd0cfb6b74e2d94a2da15b27e8e99e42f277dd12fd27ccf17bf566ad8009993", + "components/ch405labs_esp_libssh2/libssh2/src/comp.h": "7aa028c23316132522362bc9f397e22bae94e9e620eb80ac12a2009278532926", + "components/ch405labs_esp_libssh2/libssh2/src/crypt.c": "04e3683e3a16046aa7736b2401bdebea1feffc1e7fb928952dbd53adcc5a493e", + "components/ch405labs_esp_libssh2/libssh2/src/crypto.h": "9f53448f79e67731c2819b04e911228d47cb6792fe82ee818816f795cb40ffdf", + "components/ch405labs_esp_libssh2/libssh2/src/global.c": "9551963ca2fb9c321703db04952d9b05e2e6049e12d8bf6ba6e9291920b87a37", + "components/ch405labs_esp_libssh2/libssh2/src/hostkey.c": "563747e8648e09002894c1d2c93544013b17bfb3468c3e04a010306254aa865b", + "components/ch405labs_esp_libssh2/libssh2/src/keepalive.c": "acc373252f0624126226e2528897757da61c870374d5905df29a17fa185214ef", + "components/ch405labs_esp_libssh2/libssh2/src/kex.c": "f71ab4c2ba89fc4bbb560faaf955227297ece57378a984a7c67b41ef867aec1e", + "components/ch405labs_esp_libssh2/libssh2/src/knownhost.c": "2ef607c0bb2ef7ec9a4cf41158813ca8c62c55ace046a02a2b862cfdede25e75", + "components/ch405labs_esp_libssh2/libssh2/src/libgcrypt.c": "209ed04c45e4f9eeb903083853c23708d5748bcf77125664d613ffefdc2219dd", + "components/ch405labs_esp_libssh2/libssh2/src/libgcrypt.h": "7414cd0c7075c66402bed0c09fa082b40a264e50b443bc4d2d1f79991d8e5f8f", + "components/ch405labs_esp_libssh2/libssh2/src/libssh2.pc.in": "46db28ee6987b9f399c0e3b02dd5374fef2831fd4051109a478e85832e1913df", + "components/ch405labs_esp_libssh2/libssh2/src/libssh2_config_cmake.h.in": "07fe4470fd1643c51e5f2a868b053d733aaee891f1f886f4b8b848fb70db76cb", + "components/ch405labs_esp_libssh2/libssh2/src/libssh2_priv.h": "ea15b0d55cc80ff943c381e5c4758b1d6be9653b797a520ba50b8b85c5ce1818", + "components/ch405labs_esp_libssh2/libssh2/src/mac.c": "3ff6c3d22e5e9a0cc2d69b2f840606f560b83b9d40e276927d0854c20ec35b27", + "components/ch405labs_esp_libssh2/libssh2/src/mac.h": "ead9c368cf6700776d6083363a275e26d0e89de665b40b48fed1f5cd6d783b3b", + "components/ch405labs_esp_libssh2/libssh2/src/mbedtls.c": "0198525ff6b9255a7e3ab058d687fc041b3e704d1cb22584d32d6e8e57f3f133", + "components/ch405labs_esp_libssh2/libssh2/src/mbedtls.h": "c053528583d0eb839746addf0d399f86d20dfdcdac05ef977ec622f418e1177b", + "components/ch405labs_esp_libssh2/libssh2/src/misc.c": "6963f62e19e09399f871d7d3f87b16b8ea3810c8e5c38c3794b1c69efd3c1603", + "components/ch405labs_esp_libssh2/libssh2/src/misc.h": "ced7fa5c4d17e22c4f3f5407046ea0bb764ff11ca700257bfdc7728a0a89a9e9", + "components/ch405labs_esp_libssh2/libssh2/src/openssl.c": "88fa09c6324935ecee4c42f59cf5b07d069c3cc8492ab312404660fc23a7bf81", + "components/ch405labs_esp_libssh2/libssh2/src/openssl.h": "5140dd590337240cab5d2b2a4f11bb6e80b451f4e18cac77c973995b71ae49c6", + "components/ch405labs_esp_libssh2/libssh2/src/os400qc3.c": "130c4c3d3d202c4c1576cfd4fff5744e41908432ac79d8481363efe110938301", + "components/ch405labs_esp_libssh2/libssh2/src/os400qc3.h": "0e9f256b38da841315e5d82939ee52c8c947b6d1efda65f44d26cf2cd74b8db6", + "components/ch405labs_esp_libssh2/libssh2/src/packet.c": "55a13ba8b444f8cd62a9f0da3f07f982f5faf46fbf6df3bb825df1472db4c870", + "components/ch405labs_esp_libssh2/libssh2/src/packet.h": "cbd3fe922ff28675f6f39b31131d7832a07263356d0e7d55197e40d5fe244577", + "components/ch405labs_esp_libssh2/libssh2/src/pem.c": "d1adf7211b744554b8c41180c87e8d0aca2a7babceee91c75032e68655e41e22", + "components/ch405labs_esp_libssh2/libssh2/src/publickey.c": "3e1579cdc688dee088294975ee4b09316cc68cd9083ea6170a8d4726d820ea6c", + "components/ch405labs_esp_libssh2/libssh2/src/scp.c": "ef7120de5d824d9d4135b846021af8f42c44ff790dacabc8c4d23bb702abd81c", + "components/ch405labs_esp_libssh2/libssh2/src/session.c": "359f57b322d50a97ac7732bc84f22d9be9e336017a2cc9d050b06779be701bff", + "components/ch405labs_esp_libssh2/libssh2/src/session.h": "c3918ff057ebdb51116d7552e27b9f7d18461e1fbba4c1b635465dff909d4623", + "components/ch405labs_esp_libssh2/libssh2/src/sftp.c": "10a9f0076259b593fe45e71bee3b7a28ddeadfe8077a77fbbff4701cba7533f7", + "components/ch405labs_esp_libssh2/libssh2/src/sftp.h": "3b4d6460b857e32707116814f1ddc10dbfa5f804e407883e77bdad6c36db8c14", + "components/ch405labs_esp_libssh2/libssh2/src/transport.c": "77251235630878e6221516c1205b32ba786f15bd4d9afead8156a471e4312b4a", + "components/ch405labs_esp_libssh2/libssh2/src/transport.h": "4a57bc5ecc21db41729319d8fd34808f042cfa7d155be306ec2165f2d81f010c", + "components/ch405labs_esp_libssh2/libssh2/src/userauth.c": "80114428918476778385aed818ab2686a4691cdabe3b029e6d57c27431b91b22", + "components/ch405labs_esp_libssh2/libssh2/src/userauth.h": "7d930eb690721808c6d89ba917045827118a3b98b04333935d8e91b49f651b84", + "components/ch405labs_esp_libssh2/libssh2/src/userauth_kbd_packet.c": "d809a66f078569a118a944d69222ddfb5afcf0b529b245bb70725f7973a440ea", + "components/ch405labs_esp_libssh2/libssh2/src/userauth_kbd_packet.h": "f86686c43cc9ba1d9f6c8b62d801f753f350c9a3ddad3df42014fee8a2dc5eea", + "components/ch405labs_esp_libssh2/libssh2/src/version.c": "d766fe3f653d73f5a20110e7424224e788f5a42a7deadfaa8391b5a3f0694b90", + "components/ch405labs_esp_libssh2/libssh2/src/wincng.c": "c5cd20cd35a939c0b58a3311e29a8b3ba45101467a9673e693f783a31e7a636d", + "components/ch405labs_esp_libssh2/libssh2/src/wincng.h": "b9895f00d224866aac9ea1cec71ea72a2592ecd9411028ad1220869c4647edfa", + "components/ch405labs_esp_libssh2/libssh2/tests/.gitignore": "a76314b370eee3d3c44c53f5c64c9687e898909dcd3acca35aa3d483abe26e0a", + "components/ch405labs_esp_libssh2/libssh2/tests/CMakeLists.txt": "eaed8e184360a676fc5de691646a4049f7072eba226a1cef50c11cba0b55a687", + "components/ch405labs_esp_libssh2/libssh2/tests/Makefile.am": "2cd881e6ed013014f37ce5c318f39461745514c109f17e58db6bf88376908542", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/host": "6eb0f1bb23d7877ddcd502159e6673c053b5ea1846630f21651ab58ea25d7a6f", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/host.pub": "0e2479a973fbaf1f7f5dfebb111e2b199ee59c0dcfdf646d26760eba0b8b2aa8", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/sshd_config": "2ad4ea47ddb633c7a2e000f2d6619d08bf643591f26a7a0b92d0befe518ee951", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/user": "776aebc0c12e466e4b65f1a44ae5235dd70687ab03f283aa3d9a6df70d3bdbbf", + "components/ch405labs_esp_libssh2/libssh2/tests/etc/user.pub": "39bc4445c24c32fe5e64a6ee02025f3508b4334b2813e1a87c40d44ebc5f8c1d", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa": "2e5b8a618e853eff7b3e0d2928203529fe18a3ae62b46a82ccd48a750819b8c2", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa.pub": "12aecbb237794fc79d4a96cebad1c4badaa1902b3f1788cca83b28a1f977b895", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa_wrong": "21f66160d72789400c5420f460fb716cde82b5afc5c09f3f7512d310e3c8e0b2", + "components/ch405labs_esp_libssh2/libssh2/tests/key_dsa_wrong.pub": "0274eed003e62413aa894abad044296c6fb3cc19450457a282674ed3836518ea", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ecdsa": "8fb4d570516afc175869de7686125a828e18c38ddd4c2524c5a8d05c95ba7e7d", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ecdsa.pub": "bc756bc47e3afd11437cd40ebe8ce5c8fca92ee03c6e3f01b6c5b44001bbc7c6", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519": "18e808415d2f344a20b7cefac12f0df0af4e404f446f5c690000c21987ce8795", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519.pub": "e52bcbcbdcdbf547a121e92bbb6f5342375719988e33ffe7f228dd2b935c98ba", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519_encrypted": "fd1e9378f94f2d5514e16f32fcf175e8303433750c81f2def3814d5bd44a13e3", + "components/ch405labs_esp_libssh2/libssh2/tests/key_ed25519_encrypted.pub": "7ceb4062d5fe17f190eb32c894e4cfd76e00db7c1b16de7516df8f910649469d", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa": "9d8f4c955624a4af6fcb754e74e2abe1d3e7fe6340f6063617cd58bf122a2d59", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa.pub": "4293f28b7033d459618b277374d7e932869964de131bba1d427030cb5e70c297", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_encrypted": "fc3872744c7bf6db2df4ab2ea5701370cd8bd39367d659eaeae49b2dbe7bca34", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_encrypted.pub": "1f340ccab8b86e51d4ee7585d61d5e49e3a32338ba9eeca65988a1d751112c5e", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_openssh": "a146196a5b2189b40bc00bdcd1958165106ca21e72a7d02c0a7f95a6dd926487", + "components/ch405labs_esp_libssh2/libssh2/tests/key_rsa_openssh.pub": "d564da6c612286603a83af006c3a6efe53885a2417aa25f234818612e16bea66", + "components/ch405labs_esp_libssh2/libssh2/tests/libssh2_config_cmake.h.in": "193a748944f6bccd3787b1c3958ddf95c1c7ad9b25e5b8f4b42cb48987e34668", + "components/ch405labs_esp_libssh2/libssh2/tests/mansyntax.sh": "71c56796eaa4008910b3d67b885b9a7e2c018d0f88be4bb290334afb9ff23bde", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_fixture.c": "60c179e44b04a81f1bbf09aed2cb0f0dc85345070fe83b97ddf8c29219fa5d68", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_fixture.h": "21935165166ce4518c6534070cc506fcd85ece95238fef29e6b0be784c05d7c0", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/Dockerfile": "bf498e530751418dcd88ba439ad3f84837a7fa2d0f6ed2d2f2351a1097c11550", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/authorized_keys": "58c4cf998535eb4123eddf7cae7da4413eed50e3827320187380ec7925fcf61e", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_ecdsa": "14e72246d3990d345c30cd3d06c5c7ba9496057d94da2f5a6f14a7c636663206", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_ecdsa.pub": "2925ca6bb4d280aec3dd68041efc2f06e959295932a26f73a263c939c03e3220", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_rsa": "7297a4c658d398564d75964e503da94e845a0d709f64b393e3017e66dee0fb4b", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ca_rsa.pub": "338886a78519130b9bac71b7e8f370256d5b3c9d249fbfd2d7da90dd1574411f", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ssh_host_ecdsa_key": "03753b2b4942081d1f33201a193487ebd5a577e0bfde45f7e03a1de5ae404688", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ssh_host_ed25519_key": "18e808415d2f344a20b7cefac12f0df0af4e404f446f5c690000c21987ce8795", + "components/ch405labs_esp_libssh2/libssh2/tests/openssh_server/ssh_host_rsa_key": "11a57dc115ca17203d6382ad6fdcd8df33bd0f23ff6bf38ee4a697260ffd1a11", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/.gitignore": "b768be5cb4da9a7050fae93fe7b2c01073cfbc5ff40cf88ad63b6f58d0202292", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/Makefile.am": "049665a167b9f4cd664b12884ae4470c0b0b2077931a056ed55d61784b230d88", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/ossfuzz.sh": "6fde8ca30e3dfc0ade9da4d06f5e34f73a51c6fea72e3a1348cf5ced10b73d80", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/ssh2_client_fuzzer.cc": "cc7f1e67065aa6938b7e9bf8aa237d1414052c1b91ed222e2baa61e5def9bb69", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/standaloneengine.cc": "f6eb3ebf7e14252339a21fb887a08b2e7638a7ac77f706ed80508b2c0d54d81d", + "components/ch405labs_esp_libssh2/libssh2/tests/ossfuzz/testinput.h": "ce435e13e87abeec0a297ef3b566268496ecbd517c1d09dfa2232dcbbec9be2c", + "components/ch405labs_esp_libssh2/libssh2/tests/runner.c": "696b83fd77bca60560c1609212c59ad986bf151cf72520b63d23643111a7ce4e", + "components/ch405labs_esp_libssh2/libssh2/tests/session_fixture.c": "975103411a50f033df3b97b9a50136b39185dcb521765f7a6cdc52d5438e4b55", + "components/ch405labs_esp_libssh2/libssh2/tests/session_fixture.h": "d4f098a586b5f7dd0f3785b86933c08096bc12a2e55f07fff470db6fc7bbd076", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_ecdsa": "796da5d8d420f644f47feffffb0357ac99b299471e4d757f21b6cc8bfefe8f0d", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_ecdsa-cert.pub": "0f2e6d1b46874a01cc36ed766533301622d64fa88988575ca77eee56da7b3952", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_ecdsa.pub": "d6b6f80d9117f896b99933eba19b012f55068ed8b77956f1a7b0510026c2876f", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_rsa": "934d51f8e803a1c10125653a14153e6838ee9081f87eb6dbbf87f8f214a43264", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_rsa-cert.pub": "29091d3911e30d80149525c8c288e66c5a8a99fdb3816249aad5c5886df0ce5c", + "components/ch405labs_esp_libssh2/libssh2/tests/signed_key_rsa.pub": "4b742a4f19b1b468d939792135ce6a7b831dd0c8f737321c09a1281d7eb49427", + "components/ch405labs_esp_libssh2/libssh2/tests/simple.c": "4afdeef598aa669b5cd0e7388dcf2e579f2c0f9c954face71d366250101d270f", + "components/ch405labs_esp_libssh2/libssh2/tests/ssh2.c": "3a8605fd3dd6151c569bc12c07ecdc33de7d704b6224da2dedfe3c76494e015b", + "components/ch405labs_esp_libssh2/libssh2/tests/ssh2.sh": "7bbe65ee20f4e47e9264bd74700cca16ee066aba5fb9e4e42f46e1cfdae4930e", + "components/ch405labs_esp_libssh2/libssh2/tests/sshd_fixture.sh.in": "c8b93076f66222f73329472ec151b210e55b39024de5d3c18a4c609b65d13b7e", + "components/ch405labs_esp_libssh2/libssh2/tests/sshdwrap": "21649ba440cd534f4bfd52c0a8de339565768b373c172dca106cffcc8bd06e09", + "components/ch405labs_esp_libssh2/libssh2/tests/test_agent_forward_succeeds.c": "a5b9f9009c6818b86f235debc2ee15de5ceb0cfe1d9b539270167058afb4e6ac", + "components/ch405labs_esp_libssh2/libssh2/tests/test_hostkey.c": "f1059c3ac304332342f39f32288afa3f61f9bdbd5d617fe6052491b20bc0672b", + "components/ch405labs_esp_libssh2/libssh2/tests/test_hostkey_hash.c": "e745d8b4ad92c858dc588e3494e183f47d591c1ef2a13b63e2122f478545093a", + "components/ch405labs_esp_libssh2/libssh2/tests/test_keyboard_interactive_auth_fails_with_wrong_response.c": "32dfdccb447dfc0b17423cfbff8971771bf260fdb72e3c7e23ec6f62105c9fd2", + "components/ch405labs_esp_libssh2/libssh2/tests/test_keyboard_interactive_auth_info_request.c": "3e3bd0ab170d9d782a08540755030a4b1e1ad5129003381e0f19543b1005c438", + "components/ch405labs_esp_libssh2/libssh2/tests/test_keyboard_interactive_auth_succeeds_with_correct_response.c": "db57b8ed26a1314d5ef534036f383b12363d88ce54e0377086a298f276e9481c", + "components/ch405labs_esp_libssh2/libssh2/tests/test_password_auth_fails_with_wrong_password.c": "e3d588d9c6850ab69bd7674d2027563ff9f1491740637506d80875e66609974d", + "components/ch405labs_esp_libssh2/libssh2/tests/test_password_auth_fails_with_wrong_username.c": "c91608bdda3a83a62876725ae2d7002ccb3332bcbacfc9c9578e7488c0ed4cef", + "components/ch405labs_esp_libssh2/libssh2/tests/test_password_auth_succeeds_with_correct_credentials.c": "80d253225d68bcb7dc4b94b53374aa4de86c6995481de0974b6284bf87a91583", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_fails_with_wrong_key.c": "104b08aa9bb5f1006e07e59dece417a2d6a5f60ef6c3f8dc62b6a8af95d413e0", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_dsa_key.c": "4b397de742f0d2fb15e86d20451f109fedd1ba28b0622496a2d030f9e9f9ea5a", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_ecdsa_key.c": "53bd6d99a243aaedc20f7de5c974c7c04e38090a415d338cef2d7357d7644912", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_ed25519_key.c": "207f499812271669d2a9ff5a286761a45840de9230c07bf72426fcd59a682317", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_ed25519_key_from_mem.c": "4dd0a8251a41d0dd68490fb7abb9b0a1cc190af1603815f3050e29e2a7d6bc8a", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_encrypted_ed25519_key.c": "6e5c107ad53c144892c54459f89ef2cf8a25cbf977bbd978e4517cb5959a2565", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_encrypted_rsa_key.c": "dbc95a803a54364604ab379b512fc98c33d791a1df4e33e4027b881ecc2e75ed", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_rsa_key.c": "93cdd2513af42d46552baa273401910dedd014951f836175ec98b827532c5b6e", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_rsa_openssh_key.c": "4e6d3ace02cce1ba8c1b4b6e5d774a8a4d259eef8314fe6c3ae0d6003a87dcd8", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_signed_ecdsa_key.c": "f16a0dc74d16f0d27f10867f0ddd5b306fc4b16b2bd8e401a5451ce71c7649f5", + "components/ch405labs_esp_libssh2/libssh2/tests/test_public_key_auth_succeeds_with_correct_signed_rsa_key.c": "e8744ea49f5e4be9798d7ea2a93fc05bd6d4519a4bbda40dd80c421a7cc33ce6", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_config.h": "1c5c4ba6ab33bd1d9e4ce0d84e1107ced89d27a80e8505e1b428fa942edefedc", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_example.dcl": "7726a5d4f07d522aa712da8a6ca7b998cd93ca950aaa544a5eed1790dc69c775", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_help.dcl": "9d04ddc32831abf63b7e042dd0677da83599f11497d364b02cbe780419e248e4", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_kit.dcl": "e7c23c9db4583f6944cd8973cd813a6d65749170417b8384f94db69597f81f1d", + "components/ch405labs_esp_libssh2/libssh2/vms/libssh2_make_lib.dcl": "1549134cd4a4bdf2543f900ea9c811de1c67895e1e830f7ddfb384e7601f56a4", + "components/ch405labs_esp_libssh2/libssh2/vms/man2help.c": "ae61cab505a4a9c87bdd103506ba9a36fd7ba92714edd9f67d022d8a9474e6bc", + "components/ch405labs_esp_libssh2/libssh2/vms/readme.vms": "30b5d682da37cf16352152daa682cb04c56e1044c77fc4c4da77bdc9709c33b8", + "components/ch405labs_esp_libssh2/libssh2/win32/.gitignore": "06c9a331f6578cc30ba460b468e23c59fa31f5ef07c7525f5cf1c6b262d32d3e", + "components/ch405labs_esp_libssh2/libssh2/win32/GNUmakefile": "776238af38e7fb1ac52fe22c261f28e7127152184d7f561fc3ccdbc92e22b28a", + "components/ch405labs_esp_libssh2/libssh2/win32/Makefile.Watcom": "475b8b37143bad986386ca1d2c777e9f8e46d0172ca4e9f70c613c84bbdece4f", + "components/ch405labs_esp_libssh2/libssh2/win32/config.mk": "e2172a92c5b5b9f2215c5c11128009cb6ba8a1f25402990c1f7e8ae78449d289", + "components/ch405labs_esp_libssh2/libssh2/win32/libssh2.dsw": "b497be91f342d18d34c61b8e3d1d9a200c3c17c306e16a71621c467f545ca083", + "components/ch405labs_esp_libssh2/libssh2/win32/libssh2.rc": "29a25c29ed977ba78619a59bc858508caa6f0849607c02da8fa7fe71b6fb7195", + "components/ch405labs_esp_libssh2/libssh2/win32/libssh2_config.h": "d5e704c80aca43c33698bd45059eecde05b098049192bb9f0640af593cdb2cb7", + "components/ch405labs_esp_libssh2/libssh2/win32/msvcproj.foot": "d2cd7c9492045f6a9384010e9cca3c91e2a60c2e54f64680f72d94bbfcb387d2", + "components/ch405labs_esp_libssh2/libssh2/win32/msvcproj.head": "e0739f82a357ab5871aa44790521d50a80b74b5fe638c59ffb41b97c98404930", + "components/ch405labs_esp_libssh2/libssh2/win32/rules.mk": "5f68dc0a3ef0f61d783289c98c00419a0a76a2b866ecd0f86404ca1d3effc12a", + "components/ch405labs_esp_libssh2/libssh2/win32/test/GNUmakefile": "e2c77b03fa88a88d90fe1dcb6c095935ba99b03b56a78f101a373ff208e1369a", + "components/ch405labs_esp_libssh2/libssh2/win32/tests.dsp": "9c206fcca8e6ce5bb88c2278aa7d74ab8cf740d687779ffc66161ea4cc00afc0", + "components/ch405labs_esp_libssh2/libssh2_config/libssh2_config.h": "4d564e905c0f8a3eb92e55df2874b2b9ff8e589cbd6033e466129f107a3dd35e", + "components/linenoise/linenoise.c": "6401447c2b43c26130bf14302d8a2f1ccf4264598374418699722ae98460f890", + "components/ts_api/CMakeLists.txt": "f1cd2808b27affc21540be76b960bb87044b96be6a9859257563469b3724ef32", + "components/ts_api/Kconfig": "f887aa9f114a9715e286ca3d55fe77f98560cbb1cd9b4c63cd55dd5830386b64", + "components/ts_api/assets/lpmu-agx-network-setup.manifest": "8a4e7f5de0570f69c2a6a33cb2ee6c28afff763d364c7999cf70a76bf418769b", + "components/ts_api/assets/lpmu-agx-network-setup.tar.gz": "77ac9410a62eea50b2a5079d3a7adb1012deee1188c03e0a5cfb4609e4e5f636", + "components/ts_api/include/ts_api.h": "06e9e6878b7624461d9f690cecc169e684075454429e9fc21ae09f8563d6ac69", + "components/ts_api/src/ts_api.c": "56635fcd468d3f39fc06a04f6bca4dc319b8ab125b2dd93b3050bc879cf2bc14", + "components/ts_api/src/ts_api_auth.c": "be45df1d19803e7771d70f19bd5cf970f6ed51b3b20f55ad73b529fedf19c66e", + "components/ts_api/src/ts_api_automation.c": "01ac4e75a4e64b51eec7b6e5c8566c01a86ca9fe58bd3774929515f0178a3d7d", + "components/ts_api/src/ts_api_cert.c": "25af390ae3ed16eff746b2b49c3fd5893d418dc91c6106b5dbe1511f2885b7ad", + "components/ts_api/src/ts_api_config.c": "1eaf82f2f82c228de7e00c86fd3d500883107917014a5e506cd24fb60d13c667", + "components/ts_api/src/ts_api_config.c.bak": "d5f055134e303f3d724bcb65e3da8417b2d20876b2909b93403f7a3bba1d7a1c", + "components/ts_api/src/ts_api_config_pack.c": "5aa2d353b773bbd06b6235e579b540c17211534ed5440c4adfb40112f4c96968", + "components/ts_api/src/ts_api_device.c": "7f3714eb9857d069bcf6861a271ce95ed21a86b4446a99fb889486e085e5b7d5", + "components/ts_api/src/ts_api_dhcp.c": "45d3b4ccb5d6bbb3f68e424b5762daa8b0743da1575ef200b315468d65b071b2", + "components/ts_api/src/ts_api_fan.c": "41e8d20c253867f334e9b9517258c7abd6f2f34c935ca4632d27f6a627385432", + "components/ts_api/src/ts_api_gpio.c": "a508837fd3c59b00ba6df75b97e9ad496bc633b44db0167fd703b9d7cfc67284", + "components/ts_api/src/ts_api_hosts.c": "d65c9183c5064a177e594cf57a98142263542de501564d76134730b178483719", + "components/ts_api/src/ts_api_https.c.bak": "a1200dac515be89fabc14dc850c36c9df92f66834876ee25064477444b17de0d", + "components/ts_api/src/ts_api_key.c": "7b06d396f2d49f4bf17bea6eaf45f96a73712502778f912c725bf46b8aea8ca1", + "components/ts_api/src/ts_api_led.c": "d46955f01a5ee7c364c0b549cd4f035857295570f3f7be7ac8d271f684c99849", + "components/ts_api/src/ts_api_log.c": "4887b2be40a0ef3a534f86a66c1a24a7a3f3f3d07446380b7d0c65d62095cada", + "components/ts_api/src/ts_api_lpmu_access.c": "c0e2a0bf52d476a11f922213b2bd4de475cc793c6a3710aa705ffde7101b6571", + "components/ts_api/src/ts_api_monitor.c": "a33e2d70b807d8be2a752ee2a95d3e42991d3d3e84622bd725ea8680fd68420e", + "components/ts_api/src/ts_api_nat.c": "87f254d083090678b3d96fe5923dcba919405ff336608b2a29220692e21cf255", + "components/ts_api/src/ts_api_network.c": "41f60810337f7cb7ebea6646d50878aa753b7942cfa45007666d47fa26162a8d", + "components/ts_api/src/ts_api_ota.c": "0052993718bc857ac770dbbbc9b6067f8db1eefbddee5d5fe9da33b299d4bb78", + "components/ts_api/src/ts_api_power.c": "dc65cbe9c56a8478913f148ef21315878e2d9aa13518d2b20a407e05b8b2d1b3", + "components/ts_api/src/ts_api_service.c": "54638eebb7c4604713e597c1f058791e13833dd407aa9faf906dc4afb767e0ff", + "components/ts_api/src/ts_api_sftp.c": "af147747910dff5c70a21c423284764aa48ccdf0b69ec51307a080567c30c334", + "components/ts_api/src/ts_api_ssh.c": "edbf7f6a4c80f3b15a75e7b39096ca0e6fe6c98ab1cc5c3e3091b5c947646ff7", + "components/ts_api/src/ts_api_storage.c": "2d609316f08eaa00de84649cf52e38fc4c9558d10dce855dfb6c44687e12eaba", + "components/ts_api/src/ts_api_system.c": "e9668b91761222e6ef4f840feeda118e45f769ca9c86c8e9c5c6749b150ab31d", + "components/ts_api/src/ts_api_temp.c": "76dc78ecc8dac1b468e75e239ef57bef6ff84945510d626b291973f12f4b4b62", + "components/ts_api/src/ts_api_time.c": "0ebaa8796a37b1d965b51f9cf5b470d768b74a34c79c6e11184f082979c20fe0", + "components/ts_api/src/ts_api_ui.c": "ca2f0446c6cb0e42b4880fd48be4b7a52fe666a0eae3d9e828ade9289ab7358a", + "components/ts_api/src/ts_api_wifi.c": "54b7eebeced862a7bc75ef17acd9e5bb46faef526373c1a6300564a36bf0b4db", + "components/ts_auth_layout/CMakeLists.txt": "7436be669438b64ef274022bb640e47f4b009c9a0ca14b4e6128b70ba1688b33", + "components/ts_auth_layout/include/ts_auth_layout.h": "c208b11b4617c94fd0aca8041da6dbccf146cf81168a56d98afcd5f205867c2b", + "components/ts_automation/CMakeLists.txt": "5f6513d53d29951ea58531984c1c4a23d8cf9444ff9784d305cccbd13190472d", + "components/ts_automation/Kconfig": "38cc856f0951f867e771084ad7e22a8f237c4a10358f9f285bb4f4617d1f3df3", + "components/ts_automation/include/ts_action_manager.h": "af18f369c569389caf2ca033f34b234a18b724577334cc5731f9d0d449f85485", + "components/ts_automation/include/ts_automation.h": "fec1551e90c8b0e0acb0b4355c695d90213d94247659db99670c9782c69bdc08", + "components/ts_automation/include/ts_automation_types.h": "e2c9becd036d1322fdf5f40ae67df8a6d23c53f411497368e61fbe557a9d597c", + "components/ts_automation/include/ts_rule_codec.h": "501ed7dbec67e52807997cc905b41bea86d71f119cd4b31b9f460c0e0ba54a26", + "components/ts_automation/include/ts_rule_engine.h": "70d0d72afb2ebeffc278e1c844663049a5624cd2365311c0116f40f057b76a74", + "components/ts_automation/include/ts_source_manager.h": "42f2e1281ea0644a47013d3eb1a35cf6ecfc6115627b75c8fda3dfb7b4e0f78d", + "components/ts_automation/include/ts_variable.h": "136b371f4d0fab848c8c2ae15de4993b8786479af64e4c87974c8e26d1be009b", + "components/ts_automation/src/ts_action_manager.c": "837efaaa4e418681f102b9ae1b610dd05513a53fd820cbf8c55aafb00b2fc849", + "components/ts_automation/src/ts_automation.c": "be565cb980d822cbb6081a32d07e560dccbde6a254a06d0d06c10b92b9113ba8", + "components/ts_automation/src/ts_rule_codec.c": "aebb9914c282aeda99ca089ec1ed2af93efac865ee9b0e2a57d9c6abec9f828b", + "components/ts_automation/src/ts_rule_engine.c": "73e6627c2ed8aade04c3d102186fdb837415d223864a1080f9b7714d7c39b06e", + "components/ts_automation/src/ts_rule_store.c": "e96b4119e512751272ca8dc58fd553052895ecc5c742db9c47c34bf264d7772c", + "components/ts_automation/src/ts_rule_store.h": "ee248de2197d6027037980166f8a90a240214ec2c7a17c0e4097c0820e3add95", + "components/ts_automation/src/ts_source_manager.c": "4287f8ce547c360db5c30af83f62123864831730bd0fbc5b34feb522957beb0a", + "components/ts_automation/src/ts_variable.c": "9740db1f2a06a2526354cf573c1ebdd3c512bab9f9175aefaca38f8eac5c4dcf", + "components/ts_cert/CMakeLists.txt": "6d1dda73f66bc98f9f0b7c2ce62815b6838a29d3a61b7b9cfe425dbbcdfba058", + "components/ts_cert/Kconfig": "ca7b4e26d3f4387496223412d1b60286a5f0b627e1de2b72a3f1985b373aa18e", + "components/ts_cert/include/ts_cert.h": "aa04c0b71ac78426f99d4cc18d950d03ceab09039d35ff048d83c49739800406", + "components/ts_cert/include/ts_cert_time.h": "9e99dd1b179179359c620770d4b455a77bcc9160eee9fa09ec4fa33c2534eb18", + "components/ts_cert/src/ts_cert.c": "0678876ccc7534f57baeac0ed2e622171db2a512a0b926c984fa9efba4279b10", + "components/ts_cert/src/ts_cert_time.c": "4bf5e0463ff9f9e998a740cf2ff2fbe2102780e89755ac59e1c75d6d4e9f8be0", + "components/ts_config_pack/CMakeLists.txt": "ebab95266f939e82d44ad81e786b865fe6a96be4d93644d26ad7ce0f4b3367b6", + "components/ts_config_pack/Kconfig": "4f3700b1a4fc1ea6e7bfe0e241c6844fe011033cecd9ce63c6c344dc885d7a6f", + "components/ts_config_pack/include/ts_config_pack.h": "c9495aa678a2122384bbb69fe5539b79f130f3c9033b801a9d3e803c8bb2e2cc", + "components/ts_config_pack/src/ts_config_pack.c": "3041f81b2d949d10e1c0b64c7810c7cc892a8d25f27f8ed6375f1cea07fc2a80", + "components/ts_console/CMakeLists.txt": "844bd8be8bd6d63b6c0ef8118cf32b291562982346fdc7246a0d9fd03a586aee", + "components/ts_console/Kconfig": "8b835fb6fc27abc7491581c4f320ec600f70aac4874afcc78b98e280eacbaff4", + "components/ts_console/commands/ts_cmd_auto.c": "e57b47ab327f04911afe72b14edd3685db9c9bdc9a6fe46f90298483a1fd4754", + "components/ts_console/commands/ts_cmd_compute.c": "0d6395aaeaa7a93109ea25c71f53f3af11f7bb5efc1ddca05298a30460d0134d", + "components/ts_console/commands/ts_cmd_config.c": "28dc46db153b4b3a68024d5bc3ec37001df4d6d4bf7cf41e1800c4be30005d77", + "components/ts_console/commands/ts_cmd_device.c": "f3d82977bc6f499f45c04cdb02aebc67756251bc7683270823e40bfad5160b8f", + "components/ts_console/commands/ts_cmd_dhcp.c": "53609fa0ad1af0b5b91eff63b65c87a367f6fd8edec3c68cdcb30dc2f2f84145", + "components/ts_console/commands/ts_cmd_fan.c": "599db48798328646ce71fb26f19734ecf4e634fce9c4aae1da1241d92fd8f9f3", + "components/ts_console/commands/ts_cmd_fs.c": "3f236843d1b1982d48311c4ff5c6ade2e07819cba35b2823dd67e17b77aad5e7", + "components/ts_console/commands/ts_cmd_gpio.c": "33959a8512d0cfaaffd038ed3449ace567764a813fafeedbb722b1fd41dc6dea", + "components/ts_console/commands/ts_cmd_hosts.c": "645e96c17ca441cbd8cae5caf0a3b81d66f7aa9a62972efcb7d86d9acc06f040", + "components/ts_console/commands/ts_cmd_key.c": "78dd3af63ba9ee2f4e29b4b9142d17f860415ebbc5852b0bff9856c5cdb048ce", + "components/ts_console/commands/ts_cmd_led.c": "8d535e208a3ae3777468edcff5b5a01211fd1e02f600777ecf29905cf8669676", + "components/ts_console/commands/ts_cmd_monitor.c": "526c49802f6f34d4b9f5d0504eec76a3a2e06163df2bc3dee6d73a873a404b18", + "components/ts_console/commands/ts_cmd_nat.c": "cd4de61f4135904a1b063f8bcfacdfca177f38fe14f69bdac8fd6052cec0af27", + "components/ts_console/commands/ts_cmd_net.c": "5225f73d760d6da98719bf0c3551abb4366d087174487fb3246169fc232200a2", + "components/ts_console/commands/ts_cmd_ota.c": "403179e5d864a30af5289014fe2ce677cab9cecf6876802baa32d0fdf1cfd932", + "components/ts_console/commands/ts_cmd_pki.c": "85bfa318ace72dd40ac9208a3ad8af11afb33120e2e2b61de3594f2e5be4b16e", + "components/ts_console/commands/ts_cmd_power.c": "77ec359cbe492d3fb90318716c142c2408901f5e50a3c4a14073933cab7ffa8c", + "components/ts_console/commands/ts_cmd_register.c": "33adbed296353e1deb9f97efbf1139ad4c8a7ecbfa3cc661c2236f31529c4630", + "components/ts_console/commands/ts_cmd_service.c": "bb62b73286bec5d6c5f184ad8ddde9657b96042ca4ddbf75dbc60c2bb9fa3388", + "components/ts_console/commands/ts_cmd_sftp.c": "12ef96104441fb58dd07aabcfa32e28dc2617957324460700c75ea43d91e4181", + "components/ts_console/commands/ts_cmd_ssh.c": "7878385dce3d19af0a45e5dd5f264c95ce7cc0a2ee5afcd47d326adbf359c722", + "components/ts_console/commands/ts_cmd_storage.c": "9c7c581d9cbf82ccf5b91eea4c5f4683aef82ac4378bc750394f3236fa479114", + "components/ts_console/commands/ts_cmd_system.c": "1ed44e7f13f4aca20c352d734dea23150346ffc46645dab9f62e9baaac45d2db", + "components/ts_console/commands/ts_cmd_temp.c": "fb163a57281fab7d5a7732e2be9dfde0ffc169dc05d720123d0ee4fe9e6b7a0a", + "components/ts_console/commands/ts_cmd_voltprot.c": "975cf460bccc27660cc93bf0130d2bbd385369616b8ecbb48ff32096f16db3ae", + "components/ts_console/commands/ts_cmd_wifi.c": "c3042a507001b54a14b3f8ff5f32ee5d38b305d156c3267cfac2a23f2e3b3824", + "components/ts_console/include/ts_cmd_all.h": "2f76f6ec1ba074d28deb15efb4d0272607604d0b809a52fdf506b15d5659cb52", + "components/ts_console/include/ts_console.h": "f107554abcf4de2655e2bb129f5bece338ca9126e89a546b102a9bff9d92400a", + "components/ts_console/include/ts_console_args.h": "98084002ced0297f0f92824510271e56af90199442518c392d1fba3907cf624b", + "components/ts_console/include/ts_i18n.h": "9ce79a7c63c72fc49899b7614bf9a751808183de90b5ba2a228e2fffea1f1d9e", + "components/ts_console/include/ts_script.h": "a7f8c453393ac94e2c4d562b1bd8a715a21884ab7fbf1f2e19ea5acbf1ea2abf", + "components/ts_console/linenoise/linenoise.c": "ad81b74f8d3482c1dfbb37c34dac1b40a401ac5384a9c3348046ec66fa51e679", + "components/ts_console/linenoise/linenoise.h": "67d0d645bd392175ee75d4e94f2cd1bdf0eb086679d5fd77a6b90c449dd6d94a", + "components/ts_console/src/ts_console.c": "00407de9165403958c3a33c15425a4a527045ed00ab72820c3d011df52c1a6c7", + "components/ts_console/src/ts_console_args.c": "2d47c6c9ab6bead1302cdb2fcdabd14d6c0304e88a3418997965993c7e471863", + "components/ts_console/src/ts_console_builtin.c": "80eef72644309badf1181b6e98e3dc336ade99baaedfe9fba95d83df82bdfb2e", + "components/ts_console/src/ts_i18n.c": "c3d384a39ba32f27f142accb8dd17b06ca12722546332058add1490eb4f5d994", + "components/ts_console/src/ts_script.c": "034fb13082dda23578b2b20800812b59cc155fe77ed788a2247903c834b9c8f1", + "components/ts_core/CMakeLists.txt": "326c89b533f1a3a18f4a567695ef66aeca7ebe2b53ff9363ca466208e0e65905", + "components/ts_core/include/ts_core.h": "9504ead739f5011bfc7864103464bcd7d8c06eab2242d89391203164e9210197", + "components/ts_core/ts_config/CMakeLists.txt": "84e0791274bf45e4fa2c3373bfbb8f6ddcb2883c3dc7234a15fffd905a2dff9f", + "components/ts_core/ts_config/Kconfig": "7d319983a89dac10bd815eb94af1b0665a471e68709c6500ae298756161931c3", + "components/ts_core/ts_config/include/ts_config.h": "4945666dbcc7eb507f5a740061340a692e5add4ba3a4e5e421bd656d8b24b4ea", + "components/ts_core/ts_config/include/ts_config_file.h": "2d3bab9796164c3c2d945f2abd44e38dbdb37243283a62790275fe7872e65b78", + "components/ts_core/ts_config/include/ts_config_meta.h": "b649ab500111f98ba9035c525a625fc7ca21e0e553db1c978e03b35f24d43826", + "components/ts_core/ts_config/include/ts_config_module.h": "94873dac21ab86cc2f4eb4d7265588457e97e4386602773a3228c49b864bb472", + "components/ts_core/ts_config/include/ts_config_nvs.h": "2ec4ec9940dabd37df9de6f69d314583e1e77546c17fd67ccb5673a50be8a142", + "components/ts_core/ts_config/include/ts_config_schemas.h": "1b7de493a6e88d10155b558510e6ae4a72e31fbc1f77510c98b1ee8912ed94c1", + "components/ts_core/ts_config/src/ts_config.c": "c9a7b95660bfb29539cf323acd0ba66db8359a094347ea23740766a3b9721aaf", + "components/ts_core/ts_config/src/ts_config_file.c": "c61d01fec4b55560963a7995885c375f084dc54ee8ab52b47288eb68cd4403c0", + "components/ts_core/ts_config/src/ts_config_json.c": "be09570bcc58ef2dce1b4cce5968d2a0ce5a5ba0451295278ff16a66b7c32428", + "components/ts_core/ts_config/src/ts_config_meta.c": "ecf781cbcb200e56689bdaea34216cd033bf477eb1087eb1b03413334d2c92ec", + "components/ts_core/ts_config/src/ts_config_module.c": "f2c74dc811a31d4b5d0be2f2105f937ddddc5f52345763715e6fcaa6a74fbb8e", + "components/ts_core/ts_config/src/ts_config_nvs.c": "8dd95d5c09611a856e49770bc30ec971bd313cf759d833a6f97605f1dc6ef0c4", + "components/ts_core/ts_config/src/ts_config_schemas.c": "522aeba7427df30b89ab3ffb66b8637d3cf0c247af7133cdf2c04d45930994da", + "components/ts_core/ts_event/CMakeLists.txt": "c7f2d8ef1c3ac4e5bbfda512be49c5ade6acebf651ae8913e36e3f7e4ddd7506", + "components/ts_core/ts_event/Kconfig": "b1cf0bc9fa8ad38744b11d594a6f3aeb077a8ab88950c9695058e95aaea18929", + "components/ts_core/ts_event/include/ts_event.h": "16a1e76fdf93b97fbb5de2d0bd9d87d2ab8b3c9a55b1e63f1708860bc0632e4b", + "components/ts_core/ts_event/src/ts_event.c": "197c0aa5d942b10ce56fdb1245f42470e76e2827af183f905733ec84cd7faa56", + "components/ts_core/ts_jsonpath/src/ts_jsonpath.c": "115117f7a1281562ede7fe5666ba313cba8819742c8c22547a1ff0d0c9252c6f", + "components/ts_core/ts_log/CMakeLists.txt": "d149529554e03487f45cbf2f04d2989a996b328d94818614a91dfcba97c2697e", + "components/ts_core/ts_log/Kconfig": "35cb224534047beeb071dc83802e4c4532849b38d87e5feb75be5eea0634c972", + "components/ts_core/ts_log/include/ts_log.h": "beca44f4bde1ecba236f2a15d6a9bdd8037b3bb29f395e25b2f8ba4696847b57", + "components/ts_core/ts_log/src/ts_log.c": "c0cb7132cc80baa5ca03edb1adb13b0dfaa136bd4a0fd958307a43960be47b6c", + "components/ts_core/ts_log/src/ts_log_preview.h": "9e05ef9413323fc1ebe476e8fd73cf959767ceac9db7b4a5ddce17839e49b509", + "components/ts_core/ts_service/CMakeLists.txt": "ec3f90c75a8342547444c03165f61c9e9d5dfd1441598ede2aa93cf1711fac61", + "components/ts_core/ts_service/Kconfig": "3ab9397356f4485ed636b1af167714b75fc3d219386b8774ffe3bae6cfbd4675", + "components/ts_core/ts_service/include/ts_service.h": "2bbabd7738c2fb19880e45c0df169e3d5f6a226bbe1affdee030a7ddf8b2dd87", + "components/ts_core/ts_service/src/ts_service.c": "326b3ab1d4a61eba8b9bf43af26039fc4562092cbea19709764104278c79ec2b", + "components/ts_drivers/CMakeLists.txt": "22ee0589081126d02231d52d9e6526b095a4b5c13ce2cc97cb1e5666e848b8ca", + "components/ts_drivers/Kconfig": "55bfa04880f382bce54b4aae233d0f23488bd94ce8e3fac01ceee49477034427", + "components/ts_drivers/include/ts_compute_monitor.h": "b85ce79f490986e6b64ec3b12bef425576b5dec0121c0237f8cab34aab772703", + "components/ts_drivers/include/ts_device_ctrl.h": "0d203054b4b8dfe970d408c706fa1e123973b9bdc52583eec63162eee25a8879", + "components/ts_drivers/include/ts_drivers.h": "56d740b76b1401407f81099e521cd514e617fb1cdd3aaf9eab727a86dd327fd2", + "components/ts_drivers/include/ts_fan.h": "2a30df271570bff942383c46e368f232db484627bbbbb29b77a49a2155304cba", + "components/ts_drivers/include/ts_power.h": "1961071837745a2e5db6290e65bd4cdf8465a6e42b181b24f13ec642a80cc45d", + "components/ts_drivers/include/ts_power_monitor.h": "1e1b1f246f6cea8d05881e9960d2db7fd25c4185544ff8659dd8556d8f68636e", + "components/ts_drivers/include/ts_power_policy.h": "1f8475392cbaab61e90470ee0a246a67f4f8760392026318e2a56ea1058cfbc3", + "components/ts_drivers/include/ts_temp_source.h": "195c577b4f4e51efe4ad19315679dac3944f53eb72bbc94392717b3426067000", + "components/ts_drivers/include/ts_usb_mux.h": "4dde492aa085eab2024a12477036b80583b9e00a6ee3200164ec6b2b5a3b5080", + "components/ts_drivers/src/ts_compute_monitor.c": "dc396f53de43ce72b5ca6c0301d8ec82056648adce0952e0b1012e7b6a794587", + "components/ts_drivers/src/ts_device_ctrl.c": "c30a1cc807542077bd8302a9c6a4be07f286f76acb66e95f787ee9eb5fbdb279", + "components/ts_drivers/src/ts_drivers.c": "e21d531fd3bdf7024fbbd0ac7162d17602775fbe4fe237a3e0fc234ae3ed247b", + "components/ts_drivers/src/ts_fan.c": "4771e2094228dc6586be30910acc60ef44ec16f852684834eb81776e1d867431", + "components/ts_drivers/src/ts_power.c": "02d30bfe6140dcb78a0a0b26e36de7902864b323f64e5d3b6f9d6493b0d5dcc0", + "components/ts_drivers/src/ts_power_monitor.c": "22e16a8a2f0629c28f2c2f2f4d7ab259d2013be1e13943da2d0866d1a379b1d7", + "components/ts_drivers/src/ts_power_policy.c": "bc0daace30a1b4c5c14fe839f03f9af9817e9597661292be4cdf6b81e3e68957", + "components/ts_drivers/src/ts_temp_source.c": "986d608503653d071ee8e06f04560eb74403d2839add61742cc05c004b5fb153", + "components/ts_drivers/src/ts_usb_mux.c": "76687b9f9bcb1081eb2cf08ba6dd49136b3262e806db6be0756d4981bcd34470", + "components/ts_hal/CMakeLists.txt": "326df4683cb78c1ce054b3677c9346e3d94227e69d5910941a5aa766d7993e34", + "components/ts_hal/Kconfig": "708d153884fb3b7688fe223eb908d3dcce996e74bc919af2c9bd22b2f5690133", + "components/ts_hal/include/ts_hal.h": "38ba72144d7a771e4832b5ef16d11cbeda6584139efe53f953b276eebb3408a9", + "components/ts_hal/include/ts_hal_adc.h": "eb38f56f44ddc94154273649dd993d4baadc7531d62f857f64bd36489bf7b518", + "components/ts_hal/include/ts_hal_gpio.h": "aa78a98e8e5d985cb968af6bf3f3fd1fca54ba48c28e8d682ce62cba807025d7", + "components/ts_hal/include/ts_hal_i2c.h": "5f904acf2b2a4967a3477624fc8a708eefa5a78d25e8e675ad4f96e781cc609d", + "components/ts_hal/include/ts_hal_pwm.h": "c2aed39c728ad94349bb7dc5d57afe3bdd11dc825668ac4ae8ea8974d3563bca", + "components/ts_hal/include/ts_hal_spi.h": "f9b8244ebda2ce2c6876d9b33c22b0fb3c54203b9c5498df3373e2cac08f5626", + "components/ts_hal/include/ts_hal_uart.h": "c962fb9b4fc2bc210160b4c8da89b727af2f9eb24c7a2c39d9365aed2ba83133", + "components/ts_hal/include/ts_pin_manager.h": "79d1a7259afd5f367f3bdfa61484beda495b91f0bad94e66d3ec897b152bee5e", + "components/ts_hal/platform/esp32p4/ts_platform_p4.c": "92828a83921f4a1951ed820150ac450a5e6712a5ac8ffef1b4e5675a8a929854", + "components/ts_hal/platform/esp32p4/ts_platform_p4.h": "224707a735921f737c04124e2882a741b8a38e5121bc0655c1d0038795bcc987", + "components/ts_hal/platform/esp32s3/ts_platform_s3.c": "7e4155ef259b57cba342909ee23b7c6b6018790fe3b8bbde55164b782b46bb2a", + "components/ts_hal/platform/esp32s3/ts_platform_s3.h": "d6db1b661e9840a8d68ad3b3ef63e860eb65c654cec813bb502fb9a24e16e9bd", + "components/ts_hal/src/ts_adc.c": "f8899a9f1760edb6347d45799d0afbcefbf4a48ff53914426bd911c5bd13e080", + "components/ts_hal/src/ts_gpio.c": "7de7ee396a2399b0b5dad4cfc8f5213ae77b78fb30f1e47ea3225d433234cd84", + "components/ts_hal/src/ts_hal.c": "8dabc33b9a746fd7d580fad0326d74fdca89d8dffd53cbcdcc414db0a77c7c38", + "components/ts_hal/src/ts_i2c.c": "6e82ec499f6a92dd598fcc642476fdc662db8e419e1f9f86073e65a41e7c2cc9", + "components/ts_hal/src/ts_pin_manager.c": "6418d34ddcd188321df33f2ffee02b766705f03bfd39026aa3fb4082b0077b41", + "components/ts_hal/src/ts_pwm.c": "d41b742ce3a48723be2ad2b0079ff88951ae35f2ebe5622bfff91a622c4d048e", + "components/ts_hal/src/ts_spi.c": "aecc796a2e9248ba17a3658fb8dabf4a824514607eae3cd46b23298553c1222b", + "components/ts_hal/src/ts_uart.c": "8f7ea7bc94cdba23fcfe3583a32a44f279262f4f99472c9ea52d9cf31169a097", + "components/ts_https/CMakeLists.txt": "1c58f2e4f118836a66b50390efcb55192bd05b2fddf4146b9d9536a8ebdd0eaa", + "components/ts_https/Kconfig": "1992a0512508a096086de81ccd436a7998131eab99403e18fb450832d0104418", + "components/ts_https/include/ts_https.h": "5122b6cd468da5bf9637d140c48b7ed84a2655436af6f78ef6e93c33751bb26a", + "components/ts_https/include/ts_https_api.h": "70d615283a291472ad7d24f78c11a9604373e98d3192daf9638965abe7bb85f5", + "components/ts_https/src/ts_https.c": "793f542618769b8e7628b1c5343f4ad7f7134114600a7e48c2387e501d475495", + "components/ts_https/src/ts_https_api.c": "799d0998eb23398af56c3ac648de5c2f7ab8380f0ca3683388cef0259c556d63", + "components/ts_https/src/ts_https_auth.c": "37396ff1a7d181436e33eed1081147c4a10ee357daca5c1405ce4d33141c39ad", + "components/ts_https/src/ts_https_internal.h": "149a2d288607d3b624008296af19d27480bc17cb5e84bad2a96cb8cdd718609d", + "components/ts_jsonpath/CMakeLists.txt": "56990faf4de0bffe6ecab10c60d526b55feebcfdf24f56f6c4e72f6b4672f5cf", + "components/ts_jsonpath/include/ts_jsonpath.h": "88793134aeb48f2a2d659123e9f76400e204fa0504c68d49f91e11d7702c3ef1", + "components/ts_jsonpath/src/ts_jsonpath.c": "8868184035eb7d0da79ad399b95b72050874a015768b77196f9b6c1b5672af18", + "components/ts_led/CMakeLists.txt": "69170775a0baaf3c3b40c911eaa485a81d4f85bdf88f163c989ac0842dd19de6", + "components/ts_led/Kconfig": "4d411559be74736e546950c7117dd0723f8413e0de6cfda5a1d540647b2e2a09", + "components/ts_led/idf_component.yml": "3fe6ccefef850a2db760fa5e0fcba64154836f0c312e6b7575c39bac1f5a2a87", + "components/ts_led/include/ts_led.h": "2fc243661f428ac775606ac528854b7995609db60f33921688ea69d881eef283", + "components/ts_led/include/ts_led_animation.h": "fc3f6a9785772e7f4b8099ef41234f90280b54603f48724050869541370a7ee0", + "components/ts_led/include/ts_led_color_correction.h": "2256f2b5860258101818c57dc89368344f2d10fce1b44399deab6cc25f63a6e9", + "components/ts_led/include/ts_led_effect.h": "3f26f11ed916da12a139ee65952dbcdd286501b5cf09520b067197c7f66d4f57", + "components/ts_led/include/ts_led_font.h": "564b3c0ba46e5e09eeb5a92a38659ffa61809ae57985cc8998023cde36838031", + "components/ts_led/include/ts_led_image.h": "5ac7bdef1efac34a54a3a22285632c01d3e589af4a5aafef4fe069a93cd10102", + "components/ts_led/include/ts_led_preset.h": "997c4e5f7c0cb768003fb44de0daffab8dfcafa78722d40f90fab34e5880ae9b", + "components/ts_led/include/ts_led_qrcode.h": "2622472088a8b912fc1ee7eb62c30e47150da3fc16735ef139c9380090200cf8", + "components/ts_led/include/ts_led_text.h": "344687edf180d9237168b067bc513af278b3f928206019dd89b633c6d619d160", + "components/ts_led/src/qrcodegen/qrcodegen.c": "ea1770ad22a9345e22045949545f61590396935b9aec4c61e37932144d0e9339", + "components/ts_led/src/qrcodegen/qrcodegen.h": "92d80152209f9f95294b80081af9d53d1261b9b4ca8a02af480e3b554f489268", + "components/ts_led/src/ts_led.c": "f46aa8045f4154da5a5ee85cc54c3f4020dbc58d138325700d339e91d92a6801", + "components/ts_led/src/ts_led_animation.c": "03f006beb59990cfa641c3c0d0b6592d3e392684b83a45e283b282c57d248680", + "components/ts_led/src/ts_led_color.c": "e1f5743cc37b025a4e8cdd127ede6cfaa4ad2e92abc8438a2020b247aa402cc1", + "components/ts_led/src/ts_led_color_correction.c": "861a44b1f76df06dd0954d0928cfdaaacad203906ccd74458c4ed2dcec30b7c4", + "components/ts_led/src/ts_led_driver.c": "56b356ded575d34f24f74e451cabc7143fe9b793c16cc00d5c32884524d2c2ec", + "components/ts_led/src/ts_led_effect.c": "d62a66485b366fa8fbaa8e007427ef781c30a52e99a0b220c299698121a8a0ab", + "components/ts_led/src/ts_led_font.c": "52f1abfacd9d04159296ce576180894f6ae48555db70c9419a4c494d4ca1a53d", + "components/ts_led/src/ts_led_image.c": "5fb14d30ab2174a7be825ef644dcab899ffd5356c2f956814ea2ea622a74a519", + "components/ts_led/src/ts_led_layer.c": "c4521ff2fe9fc46861b1fbd66664f0e71416e396872b35a9937685de5b12cd2d", + "components/ts_led/src/ts_led_preset.c": "436d705c33fdda1a3b64da7776d9a6a26f286b6502c3e5dd0d3e08c7b6b55f15", + "components/ts_led/src/ts_led_private.h": "d871cda2b54bc1fbb91faebb7dec9b8b79065abb38f8a9bb10b482dd23145903", + "components/ts_led/src/ts_led_qrcode.c": "e2c7486363e1c5eed89fdf628378aa3e90184f4e75a11b65cc7e25852ece32d3", + "components/ts_led/src/ts_led_text.c": "50a81c95398e6f5dae971a349618567b0c11523c1a772c54295e162ee64dbb7e", + "components/ts_mempool/CMakeLists.txt": "5c6b9887ea7c01df3cd1cd1291ff64c4364d249ad0651eaa135b90f020310757", + "components/ts_mempool/include/ts_mempool.h": "448c3d3d7c7e03ef41be454f1297e79edf83334f3514da39b9c4607ec7ea85a2", + "components/ts_mempool/src/ts_mempool.c": "b160753ad6ddc0299009bf09f439aba2e9f851b0e42e0414d6c82249c92e08bf", + "components/ts_net/CMakeLists.txt": "d6aaac5a04b06bd536336820df0d5eb8c87e27b3087e5df41e640508314b163c", + "components/ts_net/Kconfig": "ddc14968f72310808d23b849248c7cb49411ed43e0f3c268060fb60da2f26e06", + "components/ts_net/include/ts_dhcp_server.h": "64e5e854f9b8fd7182f92dfafe594f3d8f1288ddecbbbec2c89b3aabee950c51", + "components/ts_net/include/ts_eth.h": "9f8952c77ade85741afb38aa48f3fb689a94164a2c598eb6c7df9344948cf8ce", + "components/ts_net/include/ts_http_server.h": "025cd54548f90be15b30d40c62250592a008b8d1e8f0dc1682ae9bef42768174", + "components/ts_net/include/ts_https_server.h": "f4c25017722b69f2f1bae48df34aa595f15d186ad3ec652b7be9d034e184bc79", + "components/ts_net/include/ts_nat.h": "1721b9c499ca0da09eb402d7db9211604a7a3414b6e2e7cf88169f872365a229", + "components/ts_net/include/ts_net.h": "2ddcd9233f0f5f63a83fdc6f3d09de3118b5b1cced5d9b009b3126c3b872a98b", + "components/ts_net/include/ts_net_manager.h": "6ad22613972f51af05eb6d468c04763808d92c1d6a6b0a7225911b24f9c0d9a5", + "components/ts_net/include/ts_time_sync.h": "e3ebf9da5b0c7b30a50a67fe07547e2c7fefd588474552579f4a2bc15ace8ca4", + "components/ts_net/include/ts_wifi.h": "25614f917387174bbbb7618010885353008e4488262303b314b87b78ae9f0905", + "components/ts_net/src/ts_dhcp_server.c": "800f32ac5097d4d73807496713a59488adfc417a1ea3be627a097cb4c9da0279", + "components/ts_net/src/ts_eth.c": "d2350045f8abe2d3bc1c046a51c5c0016b601f69bfe99ff2bfcdec8cf26e47fe", + "components/ts_net/src/ts_http_server.c": "0c8449fb396246074ef9deb404b2d5f98610f4f22f3c1ce70bf2774711dbb6ad", + "components/ts_net/src/ts_https_server.c": "50e9e0498aa7265739b99d9131eef726149fac255d20f152190d289df16b8ec9", + "components/ts_net/src/ts_nat.c": "e5accbee0cc4b7d0feccecc080b23726af94418f5f2c9645df785eb142a1eb24", + "components/ts_net/src/ts_net.c": "2f363e1c6cad3437449c742f42db70240cc34105942cfd2c2f3a854b226b8f92", + "components/ts_net/src/ts_net_manager.c": "4184c6e23f68b160a511fd8c44baa8133c04596fc00fcec459389ec61c14789f", + "components/ts_net/src/ts_time_sync.c": "d83f4591d1c45de7a89af7126c9921301a06ce2a6cb3890c5d302d491811db56", + "components/ts_net/src/ts_wifi.c": "54fdffed9cde1145b5dccc5e9419a72c94f83fbc395b225e76098be09b01ba3d", + "components/ts_ota/CMakeLists.txt": "cee899b829cbbbb31bf1e1dd5612abdf58e285381ee3896be76e12b43e116a27", + "components/ts_ota/Kconfig": "45d5a5f45174482b3adab3eca408cf641d3c0d76410d090365d4d1176e60a361", + "components/ts_ota/include/ts_ota.h": "8a41a88a13f5b32a0398c0d9a9a264f0d2afb6e078d9b9ea875e0ce65dc9487e", + "components/ts_ota/src/ts_ota.c": "862e4c0799afeaf46a6399b37f0be38e1a54d6ae7c24880da5f1453d107e5f7e", + "components/ts_ota/src/ts_ota_download.c": "0dfd39b47ee7998fb9bfd2a282fdd697792aa8a5591a1e0247c58fef060f7d31", + "components/ts_ota/src/ts_ota_https.c": "667ecf1e005a79f9f19f76e144b4b2e5e02f17edf765279e10cb19503fba397d", + "components/ts_ota/src/ts_ota_recovery.c": "e9d686d2a17e34120c4d5562f0027c0cc04b52cbafa747905bbedd465cf5f071", + "components/ts_ota/src/ts_ota_rollback.c": "d8425871467709591ae9e222ad48e9dff5373ca17467d378dddd1d6de546dfca", + "components/ts_ota/src/ts_ota_sdcard.c": "d9315d8ca0d9b319602eb63a444e164e847b370c9bcf5fb6ef81c3c7fd59746c", + "components/ts_ota/src/ts_ota_version.c": "2f8926ff4e9311cccb90402526be88eab150d1bda0303e310012875601bc17ed", + "components/ts_ota/src/ts_ota_www.c": "2825fc87003c5ef6842bfcfe4c2c3c4b50c370e4f0b5fe9bcf07daeec1ed072e", + "components/ts_pki_client/CMakeLists.txt": "1f5154b11f16b9ebf31b27aea22b5decaf1d36519b8794ca6fe378dfe5bc9f00", + "components/ts_pki_client/include/ts_pki_client.h": "bce58c6df488f53e19d80650ace1a7ca3c880b375b6c51ac3b00c9b733ce95e4", + "components/ts_pki_client/src/ts_pki_client.c": "aad64beed9ed017b467fea5098ae1ddda09a6deea856f628da9ab240e8733d26", + "components/ts_security/CMakeLists.txt": "cdc8e21b6985899e65385ce4b2c92958cc540f19f3445255301b20ad71241c88", + "components/ts_security/Kconfig": "c3d0036c138f0bf227f73558802a24892694e5f8328ecda2ab8007e0aa219a06", + "components/ts_security/include/ts_crypto.h": "371ac3b950f7185eaa21a710c4e823ed806ab337d573cfffdcfe58656aeee8c0", + "components/ts_security/include/ts_keystore.h": "55831771c42ae32640dc6ce1d7755f3487149f71f42d1f1ca7451af2ff675f40", + "components/ts_security/include/ts_known_hosts.h": "4b1244556d046e0057ba0d372498f92d263e43183975d5e55d0bbaea669b0934", + "components/ts_security/include/ts_port_forward.h": "a249f758369a81a7db44f71e4aed0511cd4f5aa932cc4bde33b29c393b5d39be", + "components/ts_security/include/ts_scp.h": "5801a44ef598560d9eef3265ec5b891b494e2682b3049834d3694abe0f86f175", + "components/ts_security/include/ts_security.h": "01cf0f2c1ee2599c0d733ac5d7466e73358fe5483aad23d654c2e6b99c039f35", + "components/ts_security/include/ts_sftp.h": "6d0c9ab1ac7dd3eab5d820798f543be18e2de1d43028dc72ca088b3ec13ab1fe", + "components/ts_security/include/ts_ssh_client.h": "ceb00ed29965279a154e061638b58769e148ea370f5435de48c90c1c8d90f928", + "components/ts_security/include/ts_ssh_commands_config.h": "d1fa1bbc2762bc4accf697db09959396cb5d82bb67ba1806a0cd4f9b45305352", + "components/ts_security/include/ts_ssh_hosts_config.h": "48d27c0cdeb6b0f462d41eaef281b6f2afe6e460b810a61f2f98278d0609280d", + "components/ts_security/include/ts_ssh_log_watch.h": "08677f37f9ee0a3620f6ed38770c4f1977d3b70787e96e57db0f934de5c5452f", + "components/ts_security/include/ts_ssh_probe.h": "697c24c0ff5244397d3483997357a81311cbd24b718d64b845efd96e19979e43", + "components/ts_security/include/ts_ssh_service.h": "73fbddabe3eaed6a191b90b1644eb50eb440509723c92f4a61788c2306596102", + "components/ts_security/include/ts_ssh_shell.h": "0594cdb6f555becc8878609039106e4d986a926be559691dd7785ec7d5d3af0e", + "components/ts_security/src/ts_auth.c": "b4456d19bb701f5be50c08bb8024c8b24eb97820fd47c72c9fda6e1ff334b78d", + "components/ts_security/src/ts_crypto.c": "5ef1140c4f122a49a531de1bff5c48c80067bdcadf2139553c35a59fd5404587", + "components/ts_security/src/ts_keystore.c": "0046e9a9f13a4dd73f932a2861b787c6264ad1597694b3cdc8a9b9eca251ea1d", + "components/ts_security/src/ts_known_hosts.c": "72e2c0c5723cf9fed7c589e46152b5806c4bdcfba565b862305d2fb299ec3844", + "components/ts_security/src/ts_port_forward.c": "b2dafd8ffc849f684cf0a9f332864876951d2d9ee7fd8a69ce7704430d00853f", + "components/ts_security/src/ts_scp.c": "cf328d792705cf8d6b00ecc3b8369ae8360fba977a3147e0a2eef6634a08cff8", + "components/ts_security/src/ts_security.c": "1c4bd91f4ab676be0739b60b826e026a84baade609369995c845b1991a1e2c49", + "components/ts_security/src/ts_sftp.c": "e05a3cd229dcf4344cfcc785755e075b52f94a4276411abbbfb6e7716793a899", + "components/ts_security/src/ts_ssh_client.c": "071b875b4029cc9d0d9e5538ce7a05921a07ec57d09faa45d295fccb7625552d", + "components/ts_security/src/ts_ssh_commands_config.c": "f12fdb5169de9e52db02590bf9d821bc08291b6c24e62f4f81bc54b03574e6da", + "components/ts_security/src/ts_ssh_hosts_config.c": "36d70ff90bef5b0efdf1195c614a33a70b7ed521807c28a2a3b4d918265b2056", + "components/ts_security/src/ts_ssh_log_watch.c": "3843930a4337ea56092d37e1ade0651dd1f6a14c3f5596d33bc83a7880712f6b", + "components/ts_security/src/ts_ssh_probe.c": "810b235d84659426a3181ec594a345e2fd0ac7fc7c1ce765c34265ad1bc05843", + "components/ts_security/src/ts_ssh_service.c": "fc345627f4f2c9417dd0e74fb47b3d77e2cc9f41fd9537bd2f633b0260e5e01c", + "components/ts_security/src/ts_ssh_shell.c": "87412b746f3a18a1937b479592e446eb737cd1f4999c316b662e5435d88ab46c", + "components/ts_storage/CMakeLists.txt": "74c30febce8cd258980e9b1d031efc32b2b268a7335e2b4f6d2b6a69be0a5e42", + "components/ts_storage/Kconfig": "95a7fd07b1765ee6f37cfa224e00dd337b9d77032d0e840fcc566f1ce7903060", + "components/ts_storage/include/ts_storage.h": "5d4e8f9cdf6669dce5b83f2a38b6f1b5c8a9e189da78d91bcff4b1add8336a41", + "components/ts_storage/src/ts_storage.c": "404f073510cc3eac90396a6c4822b0e0eeae183b95d4fa5002c0f30fd65137db", + "components/ts_storage/src/ts_storage_sd.c": "b8b028edf0cf06544fbacdaf681f387a0109a6e7364d6091007c1d2a60643b81", + "components/ts_storage/src/ts_storage_spiffs.c": "b41e67a193c9f49a9498fbfb8a5444e7db1457f1434220dfecf7bee433da8628", + "components/ts_webui/CMakeLists.txt": "53e02258893758d55edf0debef2e0694b154ecccda65ab3b5bb5d34770c39d45", + "components/ts_webui/Kconfig": "6a1fc77d34f7c635b44a922f4c7c9fb96832a9f6bb433967c26e3bdc451ae286", + "components/ts_webui/include/ts_webui.h": "374e230b4f0d016adb2373acd2e6431cf537eaeb8f7f84efcf53523d6dad0402", + "components/ts_webui/include/ts_ws_operation.h": "4a31681f9e5d0041d2627b5850b23c083e1b0ca3b876acf959adab5955611512", + "components/ts_webui/include/ts_ws_subscriptions.h": "edcfedcdb48cc47bdd776218d43f362f4f2feb84f0a8bd347b465e3dd751e3ae", + "components/ts_webui/include/ts_ws_transport.h": "4c7b996ed4e6a578ce7daa1a02a13729795bd4dca2e66eb8b49895b6f59f36ee", + "components/ts_webui/src/ts_webui.c": "6ec898b4c78fbd19e469dd45d4f890ce5bf32708a38217c516ba595c00683686", + "components/ts_webui/src/ts_webui_api.c": "c8225f3fc36be3446947e205932a3d43340665d687b81c23c16556f3be8dc9b8", + "components/ts_webui/src/ts_webui_ws.c": "cb8f801a18672c24636fe744cacf0f1e0379f75b579bcd4869bb9c9d8e541949", + "components/ts_webui/src/ts_ws_operation.c": "504ce5caa9375a792692eec681a86bf4515aa5c2d28e758d67df08117b6fe865", + "components/ts_webui/src/ts_ws_subscriptions.c": "9f8d2f33a374d6992a1ef119cd20a791244e44abc8d7cd66dc906b4896f764fb", + "components/ts_webui/src/ts_ws_transport.c": "e2eaeb31d00d7996a84badc669ca5587628c63b044c9a8014e587e84b5ab37f8", + "components/ts_webui/web/css/style.css": "30dab8799ed2a8b0a5da49ec84202b30f3c951779ea4533e847a53b2ac9b8dff", + "components/ts_webui/web/favicon.ico": "1ea04b690d7fe816da5efb405c13f9cd953366026eb3553e214de8d5df0d3648", + "components/ts_webui/web/fonts/remixicon.css": "b2218eec4e02513f0feef46f74f13c852152f54eafd83d1274057e3895f0ea1c", + "components/ts_webui/web/fonts/remixicon.woff2": "e92dc38bfb1d15dbb9d9ca9e645754f68e7c5b224e33c45a17048bd0cf2407a6", + "components/ts_webui/web/images/README.md": "f4429665c315cdabc2a935caf0f1423632dd7cbff84f34914965969217102237", + "components/ts_webui/web/images/favicon.icns": "bdc873fa7bff5e1888d80273f99f22d97d3719d4b17419e68e64eafd85c2b039", + "components/ts_webui/web/images/tslogo-128.png": "f09ac97789726872277a0399338cd9bfd0493752de930aeb6b2c6f7b0a864c3b", + "components/ts_webui/web/images/tslogo-256.png": "55dc7df59429c23fdc531baba002b7b23f5a4f2be0f29b2ecc5098f3df059da7", + "components/ts_webui/web/images/tslogo-32.png": "64e4bce72f2b13c81bef5b46ae919abeeb47f98571cf5e55460385880731810b", + "components/ts_webui/web/images/tslogo-48.png": "41f959e327dca63386a2f254b8a245a6fa151904a06eae93ae6c449277467f70", + "components/ts_webui/web/images/tslogo-512.png": "b7508585c46e16fcc7d42c52459ab55df32716aea85a10a560cd64de7cceb8e8", + "components/ts_webui/web/images/tslogo-64.png": "a0809405c5632eb4bf1f1b4783175c2b92b25fc522f5b0682a35d3cfa1c58752", + "components/ts_webui/web/images/tslogo-original.png": "9fb0ee8532c2d572d8b235f7586d225f00609cf8defb98b59cf55ae749e83ed1", + "components/ts_webui/web/index.html": "c8b08579724612166cc4ac2568aff34661bbf2c8699cc856abfa3d778ed4ae1d", + "components/ts_webui/web/js/api.js": "6fb266abb3780a0d402d86ad95a3644b8e1f488136ad44dc18ddd83caaa8dab4", + "components/ts_webui/web/js/app.js": "ad63a38112eab45af87da091f3536156614db526bb85f2c83bafa7867439230b", + "components/ts_webui/web/js/dragSort.js": "7c5b9159cb8bb88b35222424db6d8bd822d3960899d5c090c17955700d6590af", + "components/ts_webui/web/js/i18n.js": "2eed1c54b4ef89bc2e4221a3fd900e88bd8d7a11064a04d97dcc3decfdeedbd8", + "components/ts_webui/web/js/lang/en-US.js": "58beed2b903407387d884c99f38eaef578e74be916175b53745d0d5ececadc10", + "components/ts_webui/web/js/lang/zh-CN.js": "bb3d3b4b28c8c146fdb1c437bee84862806ed915af8cc0aa2388deb6a9e9ef89", + "components/ts_webui/web/js/router.js": "1e73ca3bf272a54aea8c516809e09e10f257b620bf66311bbbe358693fe377d5", + "components/ts_webui/web/js/terminal.js": "5d77a7181b6127699e098f22d3c872f5e31daaa700436b6fa928f34b6aa33e52", + "dependencies.lock": "8829663e7e611b621579e0f8d27d10b3d80e9a969d167e875f7b78597399a482", + "main/CMakeLists.txt": "c229d6b43e670fd75469edd541ad9ef51e0be3985b824ffe21e17cb8a006767c", + "main/idf_component.yml": "3f13a29a2b12e63ea4917315fa77f3481a0e26e976ffd90246312765105a4e58", + "main/main.c": "63dbd073aac40ae7ab31e92f2d52ad3f27c35fa71ade79f18c306f582bcaf40d", + "main/root_password_reset_main.c": "12d485ef6308067aaf112d8bcef71f09ba2ac60aa83a99d576635b102dadbd6c", + "main/ts_core_init.c": "ad9b89b44eef49a72117197da3e2d44a0a9ba73cbf5d1a4c7c6a7e123ea41e1f", + "main/ts_https_retry.h": "8237eca2d52e4424f9ba44674bf9202f93bd43c10f401446c17aabbcc2e5532a", + "main/ts_services.c": "697ae1b5d5472c60a93111ae21585ea23d7ccabce8e4f89b96e5982af10d7639", + "main/ts_services.h": "9631bcb3efdf01739163fde59553f50914da4eacbdb2f3f7eeb72e51a4c83c1b", + "partitions.csv": "5bea4f462b0f105e96025edfa389bfe58fe66877f27db0656b8ae830c1b96da4", + "sdkconfig": "1340e033b5865e39dd6b8c3516dffb27d01da5aff41127c69b583cbfb99acef0", + "sdkconfig.defaults": "153efe0e103cc3d7d3d6e330b931e2565a1dc92132af057b9caaf31d13c45d4e", + "tools/bdf2fnt.py": "dc156a74f206b95efd2eb5887251c55ef9c41b85330240fe2615231ddb084ca1", + "tools/build.sh": "2cb7ce21128f336eccbb75fc553341a34bf3ef3e65e4f5b99c5b09b476703466", + "tools/build_root_reset.sh": "2a59ab3eb5ae0d075ee9bf3f17582fb779c9f39c6814969bf99ded81fbf4202f", + "tools/check_release.py": "4a3a7c34bd1a0c67e9ed8d38e7daf53feb73b289826260af09fd20704d2c4d05", + "tools/gen_version.py": "92c1db10137f2e2ef8ffde87a8143e25a8bef1ab89b939a911b2ed1bdb7f650d", + "tools/minify_web.py": "c5ac7291d2c8c373463fe58e0ea8b644ea9b87fae79cccb14548488de72db008", + "tools/ota_server/README.md": "649596da0058c8bd7dce3388161711183e53078f3ac82401278f7f44c4d4e290", + "tools/ota_server/ota_server.py": "9a3c8826315fababa41b20f4f7c8ad37e3f7e507cf3633d0b5c15abc8df78356", + "tools/ota_server/ota_service.sh": "1b5145c396c94629a1605efd3dfc7ca34941a0d182327b09a168a31495972d5d", + "tools/ota_server/requirements.txt": "4dc664dd1442dea748a7c57a4645d2f0d7d4d0b7b9c9353f628c1cf1e8a6bb2e", + "tools/ota_server/start.sh": "d91b14128fe69285848c02aa42b141a3c3c958c6743c42ca2c8e48f8bb50bdb6", + "tools/ota_server/tianshan-ota.service": "f51c57579dc4e9c5bada13fb5476e9f0d7a9c8777c92278cfe5caabb9e900432", + "tools/pki-server/.env.example": "1d72a9b1c85627ebe631e709eecbf1b8c2408afddb404e0c30113a5f837470e0", + "tools/pki-server/.gitignore": "edc02d8bd09f62823287a0f4c1f90c003838d875810ba6705ba5ab70ef643643", + "tools/pki-server/README.md": "acc80cf8d621a3b1dbd4605e4a8d8d580cfe9111957e6224c0545ae578585aad", + "tools/pki-server/app/__init__.py": "d6e959bfc8628a76e60f18377a176c3c201b55d0d42c4d068d43c353f077417d", + "tools/pki-server/app/ca.py": "fc3ac5216f92393647f25f95b881e423e9cdfa0ee5272c1b8f93ae45d66f9f90", + "tools/pki-server/app/config.py": "afc6635c27892a257dbcd1bf9b815fa7353654d5d11a483a2b79cfd0c9c09c94", + "tools/pki-server/app/database.py": "80355d2a94962a2ef36c27c719f543dd8f7094554a01aca8d3b85041781546a3", + "tools/pki-server/app/main.py": "43b93ec82f7ba9aaa9589e25a0ab0576e74eb00b28e8b9fc842ee1ae4f524dd0", + "tools/pki-server/app/models.py": "b38b398d22b4ed6bd1796c461e29dbf3e538aba4b601e9725214f988ccd2ded3", + "tools/pki-server/requirements.txt": "8ccad71c5aefadd47d5b9aed26b9ef339ab64c815681e702c270328984f841b1", + "tools/pki-server/run.py": "46fa2c73203879a8079c32e52ece0a2d146a7c2ee502ecbee9a0ea40b998ceb3", + "tools/pki-server/static/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "tools/pki-server/templates/index.html": "4bf66c95d18289512f20c27e124b01d5d42de90ae86473f471e9bbbb63ab9f91", + "tools/pki-server/templates/login.html": "0a15f2e1a947ba11e9316f046830152178f3d4fe5f55561399a2f671c09ecd9f", + "tools/version.py": "15ce939bf632dfd2ce006a46cc8e31f9186215dbc824f6ba4a07ebfd9bee5315", + "components/ts_webui/web/vendor/xterm/xterm.css": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "components/ts_webui/web/vendor/xterm/LICENSE-fit": "e256f01188af527e4d06d21d06fbf785ae9c50d4b328bf03cbe0ba7f0aa4228f", + "components/ts_webui/web/vendor/xterm/fit.min.js": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "components/ts_webui/web/vendor/xterm/xterm.min.js": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "components/ts_webui/web/vendor/xterm/LICENSE-xterm": "b569f629d00f2626a8100df2a1798210535621e42164dfd426a6fe5aac7b0ccd" +} diff --git a/docs/repair/xterm-local/build.log b/docs/repair/xterm-local/build.log new file mode 100644 index 0000000..227e48a --- /dev/null +++ b/docs/repair/xterm-local/build.log @@ -0,0 +1,1676 @@ +Executing action: all (aliases: build) +Running cmake in directory /private/tmp/tianshan-xterm-final/build +Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DPYTHON=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python -DESP_PLATFORM=1 -DSDKCONFIG=/tmp/tianshan-xterm-final/sdkconfig -DCCACHE_ENABLE=0 /Users/massif/TianshanOS"... +-- Found Python3: /opt/anaconda3/bin/python3.12 (found version "3.12.4") found components: Interpreter +-- IDF_TARGET is not set, guessed 'esp32s3' from sdkconfig '/tmp/tianshan-xterm-final/sdkconfig' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +NOTICE: +Following dependencies have new versions available: +Dependency "espressif/libpng": "1.6.54" -> "1.6.58~2" +Dependency "espressif/mdns": "1.9.1" -> "1.13.1" +Dependency "espressif/zlib": "1.3.1" -> "1.3.2~1" +Consider running "idf.py update-dependencies" to update your lock file. +NOTICE: Processing 7 dependencies: +NOTICE: [1/7] espressif/esp_jpeg (1.3.1) +NOTICE: [2/7] espressif/esp_websocket_client (1.5.0) +NOTICE: [3/7] espressif/led_strip (3.0.3) +NOTICE: [4/7] espressif/libpng (1.6.54) +NOTICE: [5/7] espressif/mdns (1.9.1) +NOTICE: [6/7] espressif/zlib (1.3.1) +NOTICE: [7/7] idf (5.5.2) +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-xterm-final/sdkconfig +Loading defaults file /Users/massif/TianshanOS/sdkconfig.defaults... +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:54 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:56 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:64 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:66 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:82 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:84 line was updated to # === L2 NVS 加密配置(HMAC 方案)===n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:159 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:161 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:170 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:172 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:182 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:184 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:193 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:195 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:227 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpssep3329:229 line was updated to # ============================================================================n +-- Compiler supported targets: xtensa-esp-elf +-- Found Python3: /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python (found version "3.12.4") found components: Interpreter +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS - Success +-- USING O3 +-- App "TianShanOS" version: 0.5.2+633bb94d.09281645 +-- Adding linker script /tmp/tianshan-xterm-final/build/esp-idf/esp_system/ld/memory.ld +-- Adding linker script /tmp/tianshan-xterm-final/build/esp-idf/esp_system/ld/sections.ld.in +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Web optimization enabled (minify + gzip) +-- Components: app_trace app_update bootloader bootloader_support bt ch405labs_esp_libssh2 cmock console cxx driver efuse esp-tls esp_adc esp_app_format esp_bootloader_format esp_coex esp_common esp_driver_ana_cmpr esp_driver_bitscrambler esp_driver_cam esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_isp esp_driver_jpeg esp_driver_ledc esp_driver_mcpwm esp_driver_parlio esp_driver_pcnt esp_driver_ppa esp_driver_rmt esp_driver_sdio esp_driver_sdm esp_driver_sdmmc esp_driver_sdspi esp_driver_spi esp_driver_touch_sens esp_driver_tsens esp_driver_twai esp_driver_uart esp_driver_usb_serial_jtag esp_eth esp_event esp_gdbstub esp_hid esp_http_client esp_http_server esp_https_ota esp_https_server esp_hw_support esp_lcd esp_local_ctrl esp_mm esp_netif esp_netif_stack esp_partition esp_phy esp_pm esp_psram esp_ringbuf esp_rom esp_security esp_system esp_timer esp_vfs_console esp_wifi espcoredump espressif__esp_jpeg espressif__esp_websocket_client espressif__led_strip espressif__libpng espressif__mdns espressif__zlib esptool_py fatfs freertos hal heap http_parser idf_test ieee802154 json log lwip main mbedtls mqtt newlib nvs_flash nvs_sec_provider openthread partition_table perfmon protobuf-c protocomm pthread rt sdmmc soc spi_flash spiffs tcp_transport touch_element ts_api ts_auth_layout ts_automation ts_cert ts_config ts_config_pack ts_console ts_core ts_drivers ts_event ts_hal ts_https ts_jsonpath ts_led ts_log ts_mempool ts_net ts_ota ts_pki_client ts_security ts_service ts_storage ts_webui ulp unity usb vfs wear_levelling wifi_provisioning wpa_supplicant xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/app_trace /Users/massif/esp/v5.5.2/esp-idf/components/app_update /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/bt /Users/massif/TianshanOS/components/ch405labs_esp_libssh2 /Users/massif/esp/v5.5.2/esp-idf/components/cmock /Users/massif/esp/v5.5.2/esp-idf/components/console /Users/massif/esp/v5.5.2/esp-idf/components/cxx /Users/massif/esp/v5.5.2/esp-idf/components/driver /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp-tls /Users/massif/esp/v5.5.2/esp-idf/components/esp_adc /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_coex /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ana_cmpr /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_bitscrambler /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_cam /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_dac /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gpio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gptimer /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2c /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2s /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_isp /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_jpeg /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ledc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_mcpwm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_parlio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_pcnt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ppa /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_rmt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdspi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_spi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_touch_sens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_tsens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_twai /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_uart /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_usb_serial_jtag /Users/massif/esp/v5.5.2/esp-idf/components/esp_eth /Users/massif/esp/v5.5.2/esp-idf/components/esp_event /Users/massif/esp/v5.5.2/esp-idf/components/esp_gdbstub /Users/massif/esp/v5.5.2/esp-idf/components/esp_hid /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_client /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_ota /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_lcd /Users/massif/esp/v5.5.2/esp-idf/components/esp_local_ctrl /Users/massif/esp/v5.5.2/esp-idf/components/esp_mm /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif_stack /Users/massif/esp/v5.5.2/esp-idf/components/esp_partition /Users/massif/esp/v5.5.2/esp-idf/components/esp_phy /Users/massif/esp/v5.5.2/esp-idf/components/esp_pm /Users/massif/esp/v5.5.2/esp-idf/components/esp_psram /Users/massif/esp/v5.5.2/esp-idf/components/esp_ringbuf /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esp_timer /Users/massif/esp/v5.5.2/esp-idf/components/esp_vfs_console /Users/massif/esp/v5.5.2/esp-idf/components/esp_wifi /Users/massif/esp/v5.5.2/esp-idf/components/espcoredump /Users/massif/TianshanOS/managed_components/espressif__esp_jpeg /Users/massif/TianshanOS/managed_components/espressif__esp_websocket_client /Users/massif/TianshanOS/managed_components/espressif__led_strip /Users/massif/TianshanOS/managed_components/espressif__libpng /Users/massif/TianshanOS/managed_components/espressif__mdns /Users/massif/TianshanOS/managed_components/espressif__zlib /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/fatfs /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/heap /Users/massif/esp/v5.5.2/esp-idf/components/http_parser /Users/massif/esp/v5.5.2/esp-idf/components/idf_test /Users/massif/esp/v5.5.2/esp-idf/components/ieee802154 /Users/massif/esp/v5.5.2/esp-idf/components/json /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/lwip /Users/massif/TianshanOS/main /Users/massif/esp/v5.5.2/esp-idf/components/mbedtls /Users/massif/esp/v5.5.2/esp-idf/components/mqtt /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/nvs_flash /Users/massif/esp/v5.5.2/esp-idf/components/nvs_sec_provider /Users/massif/esp/v5.5.2/esp-idf/components/openthread /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/perfmon /Users/massif/esp/v5.5.2/esp-idf/components/protobuf-c /Users/massif/esp/v5.5.2/esp-idf/components/protocomm /Users/massif/esp/v5.5.2/esp-idf/components/pthread /Users/massif/esp/v5.5.2/esp-idf/components/rt /Users/massif/esp/v5.5.2/esp-idf/components/sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/spiffs /Users/massif/esp/v5.5.2/esp-idf/components/tcp_transport /Users/massif/esp/v5.5.2/esp-idf/components/touch_element /Users/massif/TianshanOS/components/ts_api /Users/massif/TianshanOS/components/ts_auth_layout /Users/massif/TianshanOS/components/ts_automation /Users/massif/TianshanOS/components/ts_cert /Users/massif/TianshanOS/components/ts_core/ts_config /Users/massif/TianshanOS/components/ts_config_pack /Users/massif/TianshanOS/components/ts_console /Users/massif/TianshanOS/components/ts_core /Users/massif/TianshanOS/components/ts_drivers /Users/massif/TianshanOS/components/ts_core/ts_event /Users/massif/TianshanOS/components/ts_hal /Users/massif/TianshanOS/components/ts_https /Users/massif/TianshanOS/components/ts_jsonpath /Users/massif/TianshanOS/components/ts_led /Users/massif/TianshanOS/components/ts_core/ts_log /Users/massif/TianshanOS/components/ts_mempool /Users/massif/TianshanOS/components/ts_net /Users/massif/TianshanOS/components/ts_ota /Users/massif/TianshanOS/components/ts_pki_client /Users/massif/TianshanOS/components/ts_security /Users/massif/TianshanOS/components/ts_core/ts_service /Users/massif/TianshanOS/components/ts_storage /Users/massif/TianshanOS/components/ts_webui /Users/massif/esp/v5.5.2/esp-idf/components/ulp /Users/massif/esp/v5.5.2/esp-idf/components/unity /Users/massif/esp/v5.5.2/esp-idf/components/usb /Users/massif/esp/v5.5.2/esp-idf/components/vfs /Users/massif/esp/v5.5.2/esp-idf/components/wear_levelling /Users/massif/esp/v5.5.2/esp-idf/components/wifi_provisioning /Users/massif/esp/v5.5.2/esp-idf/components/wpa_supplicant /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- +-- ╔═══════════════════════════════════════════════════════════╗ +-- ║ TianShanOS v0.5.2+633bb94d.09281645 ║ +-- ║ ESP32 Rack Management Operating System ║ +-- ╚═══════════════════════════════════════════════════════════╝ +-- +-- Version: 0.5.2+633bb94d.09281645 +-- Major: 0 +-- Minor: 5 +-- Patch: 2 +-- Build: 633bb94d.09281645 +-- +-- Target: esp32s3 +-- Build type: +-- +-- Configuring done (6.9s) +-- Generating done (0.5s) +-- Build files have been written to: /tmp/tianshan-xterm-final/build +Running ninja in directory /private/tmp/tianshan-xterm-final/build +Executing "ninja all"... +[1/1343] Generating project_elf_src_esp32s3.c +[2/1343] Generating ../../ota_data_initial.bin +[3/1343] Generating /tmp/tianshan-xterm-final/build/esp-idf/esp_system/ld/memory.ld linker script... +[4/1343] Generating /tmp/tianshan-xterm-final/build/esp-idf/esp_system/ld/sections.ld.in linker script... +[5/1343] Copying web assets to build directory +[6/1343] Generating ../../partition_table/partition-table.bin +Partition table binary generated. Contents: +******************************************************************************* +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs,data,nvs,0x9000,48K, +nvs_keys,data,nvs_keys,0x15000,4K, +otadata,data,ota,0x16000,8K, +phy_init,data,phy,0x18000,4K, +ota_0,app,ota_0,0x20000,3M, +ota_1,app,ota_1,0x320000,3M, +storage,data,spiffs,0x620000,512K, +www,data,spiffs,0x6a0000,3M, +fatfs,data,fat,0x9a0000,64K, +******************************************************************************* +[7/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_utils.c.obj +[8/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_header.c.obj +[9/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/util/ctrl_sock.c.obj +[10/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_sess.c.obj +[11/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_uri.c.obj +[12/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_main.c.obj +[13/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_auth.c.obj +[14/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_internal.c.obj +[15/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_txrx.c.obj +[16/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_ws.c.obj +[17/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport.c.obj +[18/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_socks_proxy.c.obj +[19/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_parse.c.obj +[20/1343] Building C object esp-idf/esp_https_ota/CMakeFiles/__idf_esp_https_ota.dir/src/esp_https_ota.c.obj +[21/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/system_layer/esp_psram.c.obj +[22/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/xip_impl/mmu_psram_flash.c.obj +[23/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ssl.c.obj +[24/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/esp32s3/esp_psram_impl_octal.c.obj +[25/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali.c.obj +[26/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp_adc_cal_common_legacy.c.obj +[27/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali_curve_fitting.c.obj +[28/1343] Linking C static library esp-idf/esp_https_ota/libesp_https_ota.a +[29/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_common.c.obj +[30/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/esp32s3/curve_fitting_coefficients.c.obj +[31/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp32s3/esp_adc_cal_legacy.c.obj +[32/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp-tls-crypto/esp_tls_crypto.c.obj +[33/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_platform_port.c.obj +[34/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/gdma/adc_dma.c.obj +[35/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_oneshot.c.obj +[36/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_filter.c.obj +[37/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_monitor.c.obj +[38/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_error_capture.c.obj +[39/1343] Linking C static library esp-idf/esp_http_server/libesp_http_server.a +[40/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ws.c.obj +[41/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_continuous.c.obj +[42/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/esp_http_client.c.obj +[43/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_legacy.c.obj +[44/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_dma_legacy.c.obj +[45/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls.c.obj +[46/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/sigma_delta_legacy.c.obj +[47/1343] Linking C static library esp-idf/esp_http_client/libesp_http_client.a +[48/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_mbedtls.c.obj +[49/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rtc_temperature_legacy.c.obj +[50/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/touch_sensor_common.c.obj +[51/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/timer_legacy.c.obj +[52/1343] Linking C static library esp-idf/tcp_transport/libtcp_transport.a +[53/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai.c.obj +[54/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/pcnt_legacy.c.obj +[55/1343] Building C object esp-idf/http_parser/CMakeFiles/__idf_http_parser.dir/http_parser.c.obj +[56/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/esp32s3/touch_sensor.c.obj +[57/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/i2c/i2c.c.obj +[58/1343] Linking C static library esp-idf/esp_psram/libesp_psram.a +[59/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/twai/twai.c.obj +[60/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/i2s_legacy.c.obj +[61/1343] Building C object esp-idf/esp_driver_sdm/CMakeFiles/__idf_esp_driver_sdm.dir/src/sdm.c.obj +[62/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_common.c.obj +[63/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai_onchip.c.obj +[64/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_slave.c.obj +[65/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder.c.obj +[66/1343] Linking C static library esp-idf/esp_adc/libesp_adc.a +[67/1343] Building C object esp-idf/esp_driver_tsens/CMakeFiles/__idf_esp_driver_tsens.dir/src/temperature_sensor.c.obj +[68/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_crc.c.obj +[69/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_bytes.c.obj +[70/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_common.c.obj +[71/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_copy.c.obj +[72/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/mcpwm_legacy.c.obj +[73/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_transaction.c.obj +[74/1343] Linking C static library esp-idf/esp-tls/libesp-tls.a +[75/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_simple.c.obj +[76/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rmt_legacy.c.obj +[77/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_common.c.obj +[78/1343] Linking C static library esp-idf/http_parser/libhttp_parser.a +[79/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_transaction.c.obj +[80/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_init.c.obj +[81/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sd_pwr_ctrl/sd_pwr_ctrl.c.obj +[82/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_host.c.obj +[83/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_mmc.c.obj +[84/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_cmd.c.obj +[85/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_io.c.obj +[86/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_master.c.obj +[87/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_rx.c.obj +[88/1343] Linking C static library esp-idf/driver/libdriver.a +[89/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_sd.c.obj +[90/1343] Building C object esp-idf/esp_driver_ledc/CMakeFiles/__idf_esp_driver_ledc.dir/src/ledc.c.obj +[91/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_platform.c.obj +[92/1343] Linking C static library esp-idf/esp_driver_twai/libesp_driver_twai.a +[93/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_std.c.obj +[94/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_tdm.c.obj +[95/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_com.c.obj +[96/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cmpr.c.obj +[97/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cap.c.obj +[98/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_fault.c.obj +[99/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_pdm.c.obj +[100/1343] Linking C static library esp-idf/esp_driver_ledc/libesp_driver_ledc.a +[101/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_gen.c.obj +[102/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_oper.c.obj +[103/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_sync.c.obj +[104/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_tx.c.obj +[105/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub-entry.S.obj +[106/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/xt_debugexception.S.obj +[107/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub_transport.c.obj +[108/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_timer.c.obj +[109/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/packet.c.obj +[110/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub_xtensa.c.obj +[111/1343] Linking C static library esp-idf/esp_driver_i2c/libesp_driver_i2c.a +[112/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub.c.obj +[113/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/lib_printf.c.obj +[114/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_common.c.obj +[115/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/mesh_event.c.obj +[116/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_host.c.obj +[117/1343] Linking C static library esp-idf/esp_driver_sdm/libesp_driver_sdm.a +[118/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default_ap.c.obj +[119/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig.c.obj +[120/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj +[121/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_netif.c.obj +[122/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug_diagram.c.obj +[123/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default.c.obj +[124/1343] Linking C static library esp-idf/esp_driver_tsens/libesp_driver_tsens.a +[125/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/regulatory/esp_wifi_regulatory.c.obj +[126/1343] Building C object esp-idf/esp_driver_pcnt/CMakeFiles/__idf_esp_driver_pcnt.dir/src/pulse_cnt.c.obj +[127/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_common.c.obj +[128/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug.c.obj +[129/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave.c.obj +[130/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave_hd.c.obj +[131/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/esp32s3/esp_coex_adapter.c.obj +[132/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig_ack.c.obj +[133/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32s3/esp_adapter.c.obj +[134/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/os_xtensa.c.obj +[135/1343] Linking C static library esp-idf/esp_driver_rmt/libesp_driver_rmt.a +[136/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ap_config.c.obj +[137/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/eloop.c.obj +[138/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_1x.c.obj +[139/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/comeback_token.c.obj +[140/1343] Linking C static library esp-idf/esp_driver_sdspi/libesp_driver_sdspi.a +[141/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/sta_info.c.obj +[142/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth_ie.c.obj +[143/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/pmksa_cache_auth.c.obj +[144/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_11.c.obj +[145/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/dragonfly.c.obj +[146/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_master.c.obj +[147/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/bitfield.c.obj +[148/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-kdf.c.obj +[149/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-siv.c.obj +[150/1343] Linking C static library esp-idf/esp_driver_sdmmc/libesp_driver_sdmmc.a +[151/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_ops.c.obj +[152/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/wpa_common.c.obj +[153/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-gcm.c.obj +[154/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ccmp.c.obj +[155/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_group5.c.obj +[156/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tlsprf.c.obj +[157/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-prf.c.obj +[158/1343] Linking C static library esp-idf/sdmmc/libsdmmc.a +[159/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_groups.c.obj +[160/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-tlsprf.c.obj +[161/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-tlsprf.c.obj +[162/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ms_funcs.c.obj +[163/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth.c.obj +[164/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-prf.c.obj +[165/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tprf.c.obj +[166/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-prf.c.obj +[167/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/md4-internal.c.obj +[168/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_common/eap_wsc_common.c.obj +[169/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/ieee802_11_common.c.obj +[170/1343] Linking C static library esp-idf/esp_driver_i2s/libesp_driver_i2s.a +[171/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/chap.c.obj +[172/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_common.c.obj +[173/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae.c.obj +[174/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap_common.c.obj +[175/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls.c.obj +[176/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_mschapv2.c.obj +[177/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap.c.obj +[178/1343] Linking C static library esp-idf/esp_driver_mcpwm/libesp_driver_mcpwm.a +[179/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/mschapv2.c.obj +[180/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap.c.obj +[181/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls_common.c.obj +[182/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_common.c.obj +[183/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/pmksa_cache.c.obj +[184/1343] Linking C static library esp-idf/esp_driver_pcnt/libesp_driver_pcnt.a +[185/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/ext_password.c.obj +[186/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_pac.c.obj +[187/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_ttls.c.obj +[188/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/uuid.c.obj +[189/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/base64.c.obj +[190/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpa_debug.c.obj +[191/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpabuf.c.obj +[192/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/common.c.obj +[193/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/json.c.obj +[194/1343] Linking C static library esp-idf/esp_gdbstub/libesp_gdbstub.a +[195/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa_ie.c.obj +[196/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps.c.obj +[197/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_process.c.obj +[198/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_parse.c.obj +[199/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa2_api_port.c.obj +[200/1343] Linking C static library esp-idf/esp_driver_spi/libesp_driver_spi.a +[201/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_build.c.obj +[202/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_common.c.obj +[203/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_dev_attr.c.obj +[204/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae_pk.c.obj +[205/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast.c.obj +[206/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa_main.c.obj +[207/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpas_glue.c.obj +[208/1343] Linking C static library esp-idf/esp_wifi/libesp_wifi.a +[209/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_common.c.obj +[210/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_owe.c.obj +[211/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa3.c.obj +[212/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_hostap.c.obj +[213/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_enrollee.c.obj +[214/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c.obj +[215/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpsk.c.obj +[216/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa.c.obj +[217/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls.c.obj +[218/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/rc4.c.obj +[219/1343] Linking C static library esp-idf/esp_coex/libesp_coex.a +[220/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-wrap.c.obj +[221/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpbkdf2.c.obj +[222/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_defaults.c.obj +[223/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c.obj +[224/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/des-internal.c.obj +[225/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/tls_mbedtls.c.obj +[226/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-unwrap.c.obj +[227/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_objects.c.obj +[228/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_handlers.c.obj +[229/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wps.c.obj +[230/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_eap_client.c.obj +[231/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-ccm.c.obj +[232/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-ec.c.obj +[233/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip_defaults.c.obj +[234/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj +[235/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj +[236/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj +[237/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/if_api.c.obj +[238/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj +[239/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/err.c.obj +[240/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_sntp.c.obj +[241/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/sntp/sntp.c.obj +[242/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netifapi.c.obj +[243/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netdb.c.obj +[244/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj +[245/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj +[246/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/netbiosns/netbiosns.c.obj +[247/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/def.c.obj +[248/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/init.c.obj +[249/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/sntp/sntp.c.obj +[250/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ip.c.obj +[251/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/mem.c.obj +[252/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/memp.c.obj +[253/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj +[254/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj +[255/1343] Linking C static library esp-idf/wpa_supplicant/libwpa_supplicant.a +[256/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj +[257/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/netif.c.obj +[258/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/dns.c.obj +[259/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/stats.c.obj +[260/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/sys.c.obj +[261/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/raw.c.obj +[262/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/autoip.c.obj +[263/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/timeouts.c.obj +[264/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/icmp.c.obj +[265/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj +[266/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj +[267/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj +[268/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/igmp.c.obj +[269/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj +[270/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj +[271/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj +[272/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_in.c.obj +[273/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/dhcp.c.obj +[274/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_out.c.obj +[275/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ethip6.c.obj +[276/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_frag.c.obj +[277/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/dhcp6.c.obj +[278/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/icmp6.c.obj +[279/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_napt.c.obj +[280/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/inet6.c.obj +[281/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_addr.c.obj +[282/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ccp.c.obj +[283/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/auth.c.obj +[284/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_frag.c.obj +[285/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-md5.c.obj +[286/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif.c.obj +[287/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-new.c.obj +[288/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap_ms.c.obj +[289/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/demand.c.obj +[290/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6.c.obj +[291/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj +[292/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/slipif.c.obj +[293/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/mld6.c.obj +[294/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif_fdb.c.obj +[295/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp.c.obj +[296/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eap.c.obj +[297/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ecp.c.obj +[298/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/fsm.c.obj +[299/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipcp.c.obj +[300/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eui64.c.obj +[301/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/nd6.c.obj +[302/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/lcp.c.obj +[303/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/multilink.c.obj +[304/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppapi.c.obj +[305/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipv6cp.c.obj +[306/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/magic.c.obj +[307/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ppp.c.obj +[308/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/mppe.c.obj +[309/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppol2tp.c.obj +[310/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppcrypt.c.obj +[311/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppoe.c.obj +[312/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppos.c.obj +[313/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/upap.c.obj +[314/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/utils.c.obj +[315/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/tcp_isn_default.c.obj +[316/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/vj.c.obj +[317/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/if_index.c.obj +[318/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/sockets_ext.c.obj +[319/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/acd_dhcp_check.c.obj +[320/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md4.c.obj +[321/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/freertos/sys_arch.c.obj +[322/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/arc4.c.obj +[323/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping.c.obj +[324/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32xx/vfs_lwip.c.obj +[325/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md5.c.obj +[326/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/des.c.obj +[327/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/debug/lwip_debug.c.obj +[328/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/esp_ping.c.obj +[329/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/sha1.c.obj +[330/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/lwip_default_hooks.c.obj +[331/1343] Linking C static library esp-idf/esp_netif/libesp_netif.a +[332/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping_sock.c.obj +[333/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/lib_printf.c.obj +[334/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/esp32s3/phy_init_data.c.obj +[335/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_connection_monitor.c.obj +[336/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/nullfs.c.obj +[337/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_common.c.obj +[338/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj +[339/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/dhcpserver/dhcpserver.c.obj +[340/1343] Building C object esp-idf/esp_vfs_console/CMakeFiles/__idf_esp_vfs_console.dir/vfs_console.c.obj +[341/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/btbb_init.c.obj +[342/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_eventfd.c.obj +[343/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag.c.obj +[344/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_vfs.c.obj +[345/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_semihost.c.obj +[346/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj +[347/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_platform.cpp.obj +[348/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs.c.obj +[349/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader.c.obj +[350/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_aes.c.obj +[351/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_xts_aes.c.obj +[352/1343] Linking C static library esp-idf/lwip/liblwip.a +[353/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition.cpp.obj +[354/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_lookup.cpp.obj +[355/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/default_event_loop.c.obj +[356/1343] Linking C static library esp-idf/vfs/libvfs.a +[357/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event_private.c.obj +[358/1343] Linking C static library esp-idf/esp_vfs_console/libesp_vfs_console.a +[359/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_wakeup.c.obj +[360/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event.c.obj +[361/1343] Linking C static library esp-idf/esp_driver_usb_serial_jtag/libesp_driver_usb_serial_jtag.a +[362/1343] Linking C static library esp-idf/esp_phy/libesp_phy.a +[363/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uhci.c.obj +[364/1343] Building C object esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj +[365/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_vfs.c.obj +[366/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer_common.c.obj +[367/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_init.c.obj +[368/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer.c.obj +[369/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj +[370/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj +[371/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj +[372/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj +[373/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart.c.obj +[374/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_exception_stubs.cpp.obj +[375/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_init.cpp.obj +[376/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj +[377/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj +[378/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_cond_var.c.obj +[379/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_local_storage.c.obj +[380/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_guards.cpp.obj +[381/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_rwlock.c.obj +[382/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/init.c.obj +[383/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_semaphore.c.obj +[384/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/abort.c.obj +[385/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/assert.c.obj +[386/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/heap.c.obj +[387/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/poll.c.obj +[388/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/getentropy.c.obj +[389/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/pthread.c.obj +[390/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/random.c.obj +[391/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/locks.c.obj +[392/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/termios.c.obj +[393/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/realpath.c.obj +[394/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/sysconf.c.obj +[395/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/time.c.obj +[396/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/scandir.c.obj +[397/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_item_hash_list.cpp.obj +[398/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/syscalls.c.obj +[399/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_syscalls.c.obj +[400/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/esp_time_impl.c.obj +[401/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/flockfile.c.obj +[402/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_init.c.obj +[403/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/xtensa/stdatomic_s32c1i.c.obj +[404/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/stdatomic.c.obj +[405/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/newlib_init.c.obj +[406/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj +[407/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_types.cpp.obj +[408/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/app_startup.c.obj +[409/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj +[410/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj +[411/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj +[412/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_pagemanager.cpp.obj +[413/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_locked.cpp.obj +[414/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_cxx_api.cpp.obj +[415/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_simple.cpp.obj +[416/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_encrypted_partition.cpp.obj +[417/1343] Building ASM object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/portasm.S.obj +[418/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/event_groups.c.obj +[419/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_init.c.obj +[420/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/stream_buffer.c.obj +[421/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_page.cpp.obj +[422/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/timers.c.obj +[423/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_overlay_os_hook.c.obj +[424/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions_event_groups.c.obj +[425/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj +[426/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/freertos_compatibility.c.obj +[427/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[428/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions.c.obj +[429/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/port.c.obj +[430/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[431/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[432/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_manager.cpp.obj +[433/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[434/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj +[435/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_storage.cpp.obj +[436/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/revision.c.obj +[437/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_gpio_reserve.c.obj +[438/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_ctrl_os.c.obj +[439/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj +[440/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mac_addr.c.obj +[441/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_api.cpp.obj +[442/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj +[443/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sar_periph_ctrl_common.c.obj +[444/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj +[445/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_clk_tree.c.obj +[446/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/io_mux.c.obj +[447/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj +[448/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj +[449/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj +[450/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma_link.c.obj +[451/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_dma_utils.c.obj +[452/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_utils.c.obj +[453/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_mspi.c.obj +[454/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_usb.c.obj +[455/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_clk_tree_common.c.obj +[456/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modem.c.obj +[457/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_console.c.obj +[458/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_bus_lock.c.obj +[459/1343] Linking C static library esp-idf/nvs_flash/libnvs_flash.a +[460/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_event.c.obj +[461/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/systimer.c.obj +[462/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/adc_share_hw_ctrl.c.obj +[463/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_share_hw_ctrl.c.obj +[464/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_async_memcpy.c.obj +[465/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_gpio.c.obj +[466/1343] Linking C static library esp-idf/esp_event/libesp_event.a +[467/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_wake_stub.c.obj +[468/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/deprecated/gdma_legacy.c.obj +[469/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/mspi_timing_tuning.c.obj +[470/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[471/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/power_supply/brownout.c.obj +[472/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[473/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[474/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/async_memcpy_gdma.c.obj +[475/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[476/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[477/1343] Linking C static library esp-idf/esp_driver_uart/libesp_driver_uart.a +[478/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clock_output.c.obj +[479/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[480/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_memprot_conv.c.obj +[481/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/sar_periph_ctrl.c.obj +[482/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_config.c.obj +[483/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[484/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_lock.c.obj +[485/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/init.c.obj +[486/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[487/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c.obj +[488/1343] Linking C static library esp-idf/esp_ringbuf/libesp_ringbuf.a +[489/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[490/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_hmac.c.obj +[491/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma.c.obj +[492/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_ds.c.obj +[493/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/lowpower/port/esp32s3/sleep_cpu.c.obj +[494/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_periph_clk.c.obj +[495/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[496/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[497/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[498/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[499/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[500/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[501/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[502/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[503/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[504/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[505/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[506/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[507/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[508/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[509/1343] Linking C static library esp-idf/esp_driver_gptimer/libesp_driver_gptimer.a +[510/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[511/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[512/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[513/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[514/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[515/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[516/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[517/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[518/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[519/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[520/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[521/1343] Linking C static library esp-idf/esp_timer/libesp_timer.a +[522/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/esp32s3/memory_layout.c.obj +[523/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj +[524/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_timestamp.c.obj +[525/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj +[526/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[527/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj +[528/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_init.c.obj +[529/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/util.c.obj +[530/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[531/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[532/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/memory_layout_utils.c.obj +[533/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj +[534/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_lock.c.obj +[535/1343] Linking C static library esp-idf/cxx/libcxx.a +[536/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[537/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[538/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_memprot.c.obj +[539/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/tag_log_level.c.obj +[540/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[541/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_write.c.obj +[542/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/log_level.c.obj +[543/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/linked_list/log_linked_list.c.obj +[544/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[545/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[546/1343] Linking C static library esp-idf/pthread/libpthread.a +[547/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/color_hal.c.obj +[548/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[549/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[550/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/cache/log_binary_heap.c.obj +[551/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[552/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[553/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_encrypt_hal_iram.c.obj +[554/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj +[555/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gpio_hal.c.obj +[556/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal.c.obj +[557/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/timer_hal.c.obj +[558/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal_iram.c.obj +[559/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rtc_io_hal.c.obj +[560/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal_iram.c.obj +[561/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal_iram.c.obj +[562/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rmt_hal.c.obj +[563/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal.c.obj +[564/1343] Linking C static library esp-idf/newlib/libnewlib.a +[565/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal.c.obj +[566/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal.c.obj +[567/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/clk_tree_hal.c.obj +[568/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/pcnt_hal.c.obj +[569/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj +[570/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uhci_hal.c.obj +[571/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mcpwm_hal.c.obj +[572/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_top.c.obj +[573/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdm_hal.c.obj +[574/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdmmc_hal.c.obj +[575/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_ahb_v1.c.obj +[576/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal_common.c.obj +[577/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/twai_hal_v1.c.obj +[578/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2s_hal.c.obj +[579/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/lcd_hal.c.obj +[580/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpi_hal.c.obj +[581/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj +[582/1343] Linking C static library esp-idf/freertos/libfreertos.a +[583/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sha_hal.c.obj +[584/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_oneshot_hal.c.obj +[585/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/aes_hal.c.obj +[586/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal.c.obj +[587/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal.c.obj +[588/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hmac_hal.c.obj +[589/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal_iram.c.obj +[590/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_serial_jtag_hal.c.obj +[591/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ds_hal.c.obj +[592/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_wrap_hal.c.obj +[593/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal.c.obj +[594/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cam_hal.c.obj +[595/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/touch_sensor_hal.c.obj +[596/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[597/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hd_hal.c.obj +[598/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_dwc_hal.c.obj +[599/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sens_hal.c.obj +[600/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sensor_hal.c.obj +[601/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal_iram.c.obj +[602/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj +[603/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/xt_wdt_hal.c.obj +[604/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/tlsf/tlsf.c.obj +[605/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[606/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[607/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[608/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[609/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[610/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[611/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[612/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/rtc_cntl_hal.c.obj +[613/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[614/1343] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[615/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[616/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[617/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[618/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[619/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj +[620/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system_console.c.obj +[621/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj +[622/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj +[623/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_ipc.c.obj +[624/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/stack_check.c.obj +[625/1343] Linking C static library esp-idf/esp_security/libesp_security.a +[626/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup.c.obj +[627/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/system_time.c.obj +[628/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj +[629/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj +[630/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/panic.c.obj +[631/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/xt_wdt.c.obj +[632/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup_funcs.c.obj +[633/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_routines.S.obj +[634/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_handler.S.obj +[635/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_handler_asm.S.obj +[636/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj +[637/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj +[638/1343] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[639/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj +[640/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack_asm.S.obj +[641/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_port.c.obj +[642/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj +[643/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/image_process.c.obj +[644/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_ipc_isr.c.obj +[645/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_arch.c.obj +[646/1343] Linking C static library esp-idf/soc/libsoc.a +[647/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers_asm.S.obj +[648/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj +[649/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack.c.obj +[650/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/highint_hdl.S.obj +[651/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_stubs.c.obj +[652/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj +[653/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/trax.c.obj +[654/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers.c.obj +[655/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/reset_reason.c.obj +[656/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/cache_err_int.c.obj +[657/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/apb_backup_dma.c.obj +[658/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_hpm_enable.c.obj +[659/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp32s3/spi_flash_oct_flash_init.c.obj +[660/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/system_internal.c.obj +[661/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_issi.c.obj +[662/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_drivers.c.obj +[663/1343] Linking C static library esp-idf/heap/libheap.a +[664/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/clk.c.obj +[665/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic.c.obj +[666/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_gd.c.obj +[667/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_boya.c.obj +[668/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_th.c.obj +[669/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_generic.c.obj +[670/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_winbond.c.obj +[671/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic_opi.c.obj +[672/1343] Linking C static library esp-idf/log/liblog.a +[673/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/memspi_host_driver.c.obj +[674/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[675/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj +[676/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj +[677/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/port/esp32s3/ext_mem_layout.c.obj +[678/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj +[679/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj +[680/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj +[681/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_msync.c.obj +[682/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/heap_align_hw.c.obj +[683/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_spi_init.c.obj +[684/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_utils.c.obj +[685/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[686/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj +[687/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[688/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[689/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_api.c.obj +[690/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[691/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[692/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[693/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[694/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[695/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[696/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[697/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/secure_boot_secure_features.c.obj +[698/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[699/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[700/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[701/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[702/1343] Linking C static library esp-idf/hal/libhal.a +[703/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[704/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[705/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[706/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[707/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_startup.c.obj +[708/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_app_desc.c.obj +[709/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[710/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[711/1343] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[712/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition_target.c.obj +[713/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[714/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/debug.c.obj +[715/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[716/1343] Linking C static library esp-idf/esp_rom/libesp_rom.a +[717/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[718/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_reader.c.obj +[719/1343] Building C object esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj +[720/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition.c.obj +[721/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_trace.c.obj +[722/1343] Linking C static library esp-idf/esp_common/libesp_common.a +[723/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_server.c.obj +[724/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_keys.c.obj +[725/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_client.c.obj +[726/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_debug_helpers_generated.c.obj +[727/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cache.c.obj +[728/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ciphersuites.c.obj +[729/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cookie.c.obj +[730/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[731/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ticket.c.obj +[732/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_client.c.obj +[733/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_generic.c.obj +[734/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_platform_time.c.obj +[735/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/mbedtls_debug.c.obj +[736/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_ops.c.obj +[737/1343] Linking C static library esp-idf/esp_system/libesp_system.a +[738/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_create.c.obj +[739/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write.c.obj +[740/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/pkcs7.c.obj +[741/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crl.c.obj +[742/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_csr.c.obj +[743/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesni.c.obj +[744/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_csr.c.obj +[745/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/net_sockets.c.obj +[746/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_server.c.obj +[747/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesce.c.obj +[748/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_crt.c.obj +[749/1343] Linking C static library esp-idf/spi_flash/libspi_flash.a +[750/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aes.c.obj +[751/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_client.c.obj +[752/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_msg.c.obj +[753/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1parse.c.obj +[754/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1write.c.obj +[755/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aria.c.obj +[756/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/block_cipher.c.obj +[757/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod.c.obj +[758/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod_raw.c.obj +[759/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509.c.obj +[760/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/base64.c.obj +[761/1343] Linking C static library esp-idf/esp_mm/libesp_mm.a +[762/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/camellia.c.obj +[763/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chacha20.c.obj +[764/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chachapoly.c.obj +[765/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ccm.c.obj +[766/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_core.c.obj +[767/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/dhm.c.obj +[768/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/constant_time.c.obj +[769/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/des.c.obj +[770/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher_wrap.c.obj +[771/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecjpake.c.obj +[772/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ctr_drbg.c.obj +[773/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cmac.c.obj +[774/1343] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[775/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher.c.obj +[776/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crt.c.obj +[777/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdh.c.obj +[778/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves_new.c.obj +[779/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy_poll.c.obj +[780/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdsa.c.obj +[781/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hkdf.c.obj +[782/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy.c.obj +[783/1343] Linking C static library esp-idf/efuse/libefuse.a +[784/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hmac_drbg.c.obj +[785/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/memory_buffer_alloc.c.obj +[786/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/nist_kw.c.obj +[787/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md5.c.obj +[788/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lmots.c.obj +[789/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/error.c.obj +[790/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lms.c.obj +[791/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/gcm.c.obj +[792/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves.c.obj +[793/1343] Linking C static library esp-idf/esp_partition/libesp_partition.a +[794/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/padlock.c.obj +[795/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum.c.obj +[796/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md.c.obj +[797/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_ecc.c.obj +[798/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pem.c.obj +[799/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls.c.obj +[800/1343] Linking C static library esp-idf/app_update/libapp_update.a +[801/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/poly1305.c.obj +[802/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform.c.obj +[803/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform_util.c.obj +[804/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs12.c.obj +[805/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_wrap.c.obj +[806/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk.c.obj +[807/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs5.c.obj +[808/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkwrite.c.obj +[809/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/oid.c.obj +[810/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_client.c.obj +[811/1343] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[812/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_cipher.c.obj +[813/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_driver_wrappers_no_static.c.obj +[814/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_aead.c.obj +[815/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_hash.c.obj +[816/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_se.c.obj +[817/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp.c.obj +[818/1343] Linking C static library esp-idf/esp_app_format/libesp_app_format.a +[819/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_mac.c.obj +[820/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ffdh.c.obj +[821/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkparse.c.obj +[822/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_pake.c.obj +[823/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_its_file.c.obj +[824/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ripemd160.c.obj +[825/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_rsa.c.obj +[826/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ecp.c.obj +[827/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_storage.c.obj +[828/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha3.c.obj +[829/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_slot_management.c.obj +[830/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_util.c.obj +[831/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa_alt_helpers.c.obj +[832/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha1.c.obj +[833/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha256.c.obj +[834/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/threading.c.obj +[835/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/timing.c.obj +[836/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version.c.obj +[837/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version_features.c.obj +[838/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha512.c.obj +[839/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedtls.a +[840/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha_gdma_impl.c.obj +[841/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_gdma_impl.c.obj +[842/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_mem.c.obj +[843/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hardware.c.obj +[844/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_timing.c.obj +[845/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c.obj +[846/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_common.c.obj +[847/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_dma_core.c.obj +[848/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c.obj +[849/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_xts.c.obj +[850/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hmac_pbkdf2.c.obj +[851/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/esp_sha.c.obj +[852/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_dec_alt.c.obj +[853/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/bignum_alt.c.obj +[854/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa.c.obj +[855/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_ds_common.c.obj +[856/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/esp_bignum.c.obj +[857/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha512.c.obj +[858/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c.obj +[859/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha1.c.obj +[860/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha256.c.obj +[861/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedx509.a +[862/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/md/esp_md.c.obj +[863/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/x25519.c.obj +[864/1343] Creating directories for 'bootloader' +[865/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/sha.c.obj +[866/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/everest.c.obj +[867/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m/p256-m.c.obj +[868/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m_driver_entrypoints.c.obj +[869/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/Hacl_Curve25519_joined.c.obj +[870/1343] No download step for 'bootloader' +[871/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_gcm.c.obj +[872/1343] No update step for 'bootloader' +[873/1343] No patch step for 'bootloader' +[874/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto.c.obj +[875/1343] Minifying + gzipping web resources +Minifying web resources in /tmp/tianshan-xterm-final/build/esp-idf/ts_webui/web_optimized... + JS js/terminal.js: 31,108 -> 20,066 (35.5% saved) + JS js/router.js: 6,414 -> 3,839 (40.1% saved) + JS js/dragSort.js: 11,460 -> 7,603 (33.7% saved) + JS js/api.js: 36,638 -> 24,339 (33.6% saved) + JS js/i18n.js: 7,208 -> 4,320 (40.1% saved) + JS js/app.js: 1,129,944 -> 840,829 (25.6% saved) + JS js/lang/en-US.js: 178,439 -> 143,161 (19.8% saved) + JS js/lang/zh-CN.js: 172,046 -> 137,314 (20.2% saved) + CSS css/style.css: 179,071 -> 129,275 (27.8% saved) + CSS fonts/remixicon.css: 5,940 -> 4,860 (18.2% saved) + + Total saved: 442,662 bytes (432.3 KB) + +Gzipping web resources in /tmp/tianshan-xterm-final/build/esp-idf/ts_webui/web_optimized... + GZ js/terminal.js: 20,066 -> 5,565 (72.3% smaller) + GZ js/router.js: 3,839 -> 1,340 (65.1% smaller) + GZ js/dragSort.js: 7,603 -> 1,869 (75.4% smaller) + GZ js/api.js: 24,339 -> 6,163 (74.7% smaller) + GZ js/i18n.js: 4,320 -> 1,460 (66.2% smaller) + GZ js/app.js: 840,829 -> 167,747 (80.0% smaller) + GZ js/lang/en-US.js: 143,161 -> 43,017 (70.0% smaller) + GZ js/lang/zh-CN.js: 137,314 -> 45,286 (67.0% smaller) + GZ vendor/xterm/fit.min.js: 1,789 -> 822 (54.1% smaller) + GZ vendor/xterm/xterm.min.js: 283,670 -> 65,684 (76.8% smaller) + GZ css/style.css: 129,275 -> 20,658 (84.0% smaller) + GZ fonts/remixicon.css: 4,860 -> 1,263 (74.0% smaller) + GZ vendor/xterm/xterm.css: 5,383 -> 2,037 (62.2% smaller) + GZ index.html: 26,676 -> 7,261 (72.8% smaller) + + Gzipped 14 files: 1,633,124 -> 370,172 (77.3% overall) +Done. +[876/1343] cd /tmp/tianshan-xterm-final/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-xterm-final/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-xterm-final/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +[877/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a +[878/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/p256-m/libp256m.a +[879/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/3rdparty/everest/libeverest.a +[880/1343] Generating x509_crt_bundle +[881/1343] Generating ../../x509_crt_bundle.S +[882/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[883/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr_asm.S.obj +[884/1343] Building ASM object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/__/__/x509_crt_bundle.S.obj +[885/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_context.S.obj +[886/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[887/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_trace.c.obj +[888/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_glitch_filter_ops.c.obj +[889/1343] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_intr.c.obj +[890/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_locks.c.obj +[891/1343] Building ASM object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xtensa_vectors.S.obj +[892/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio_pin_glitch_filter.c.obj +[893/1343] Building C object esp-idf/esp_pm/CMakeFiles/__idf_esp_pm.dir/pm_impl.c.obj +[894/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/crc32.cpp.obj +[895/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/SPI_Flash.cpp.obj +[896/1343] Building C object esp-idf/mbedtls/CMakeFiles/__idf_mbedtls.dir/esp_crt_bundle/esp_crt_bundle.c.obj +[897/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/Partition.cpp.obj +[898/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/dedic_gpio.c.obj +[899/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/rtc_io.c.obj +[900/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Perf.cpp.obj +[901/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Ext_Safe.cpp.obj +[902/1343] Linking C static library esp-idf/mbedtls/libmbedtls.a +[903/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio.c.obj +[904/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_rawflash.c.obj +[905/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/wear_levelling.cpp.obj +[906/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_wl.c.obj +[907/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/port/freertos/ffsystem.c.obj +[908/1343] Building C object esp-idf/esp_driver_gpio/CMakeFiles/__idf_esp_driver_gpio.dir/src/gpio.c.obj +[909/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ffunicode.c.obj +[910/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/diskio/diskio_sdmmc.c.obj +[911/1343] Linking C static library esp-idf/esp_pm/libesp_pm.a +[912/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs_api.c.obj +[913/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_spiflash.c.obj +[914/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_cache.c.obj +[915/1343] Linking C static library esp-idf/esp_driver_gpio/libesp_driver_gpio.a +[916/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/split_argv.c.obj +[917/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_common.c.obj +[918/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat_sdmmc.c.obj +[919/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_gc.c.obj +[920/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/commands.c.obj +[921/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_internal.c.obj +[922/1343] Linking C static library esp-idf/xtensa/libxtensa.a +[923/1343] Building CXX object esp-idf/wear_levelling/CMakeFiles/__idf_wear_levelling.dir/WL_Flash.cpp.obj +[924/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_check.c.obj +[925/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_hydrogen.c.obj +[926/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/linenoise/linenoise.c.obj +[927/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_end.c.obj +[928/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/vfs/vfs_fat.c.obj +[929/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_cmd.c.obj +[930/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/esp_spiffs.c.obj +[931/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dbl.c.obj +[932/1343] Linking C static library esp-idf/wear_levelling/libwear_levelling.a +[933/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_dstr.c.obj +[934/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/esp_console_repl_chip.c.obj +[935/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_file.c.obj +[936/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_date.c.obj +[937/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_lit.c.obj +[938/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_hashtable.c.obj +[939/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_int.c.obj +[940/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_str.c.obj +[941/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rem.c.obj +[942/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_utils.c.obj +[943/1343] Building C object esp-idf/spiffs/CMakeFiles/__idf_spiffs.dir/spiffs/src/spiffs_nucleus.c.obj +[944/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth_netif_glue.c.obj +[945/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/argtable3.c.obj +[946/1343] Building C object esp-idf/console/CMakeFiles/__idf_console.dir/argtable3/arg_rex.c.obj +[947/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/adler32.c.obj +[948/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/compress.c.obj +[949/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_phy_w5500.c.obj +[950/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/esp_eth.c.obj +[951/1343] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON_Utils.c.obj +[952/1343] Linking C static library esp-idf/spiffs/libspiffs.a +[953/1343] Building C object esp-idf/ts_event/CMakeFiles/__idf_ts_event.dir/src/ts_event.c.obj +[954/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/phy/esp_eth_phy_802_3.c.obj +[955/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/crc32.c.obj +[956/1343] Building C object esp-idf/fatfs/CMakeFiles/__idf_fatfs.dir/src/ff.c.obj +[957/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzclose.c.obj +[958/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inffast.c.obj +[959/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/uncompr.c.obj +[960/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzlib.c.obj +[961/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzread.c.obj +[962/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/infback.c.obj +[963/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/zutil.c.obj +[964/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inftrees.c.obj +[965/1343] Building C object esp-idf/esp_eth/CMakeFiles/__idf_esp_eth.dir/src/spi/w5500/esp_eth_mac_w5500.c.obj +[966/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/gzwrite.c.obj +[967/1343] Linking C static library esp-idf/fatfs/libfatfs.a +[968/1343] Linking C static library esp-idf/ts_event/libts_event.a +[969/1343] Building C object esp-idf/json/CMakeFiles/__idf_json.dir/cJSON/cJSON.c.obj +[970/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_encoder.c.obj +[971/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/trees.c.obj +[972/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/example.c.obj +[973/1343] Linking C static library esp-idf/console/libconsole.a +[974/1343] Linking C static library esp-idf/esp_eth/libesp_eth.a +[975/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_api.c.obj +[976/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_rmt_dev.c.obj +[977/1343] Linking C static library esp-idf/json/libjson.a +[978/1343] Building C object esp-idf/espressif__esp_jpeg/CMakeFiles/__idf_espressif__esp_jpeg.dir/jpeg_decoder.c.obj +[979/1343] Building C object esp-idf/espressif__led_strip/CMakeFiles/__idf_espressif__led_strip.dir/src/led_strip_spi_dev.c.obj +[980/1343] Building C object esp-idf/esp_https_server/CMakeFiles/__idf_esp_https_server.dir/src/https_server.c.obj +[981/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/inflate.c.obj +[982/1343] Building C object esp-idf/espressif__zlib/CMakeFiles/__idf_espressif__zlib.dir/zlib/deflate.c.obj +[983/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngmem.c.obj +[984/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrio.c.obj +[985/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngerror.c.obj +[986/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngpread.c.obj +[987/1343] Building C object esp-idf/ts_log/CMakeFiles/__idf_ts_log.dir/src/ts_log.c.obj +[988/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtrans.c.obj +[989/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwio.c.obj +[990/1343] Linking C static library esp-idf/espressif__zlib/libespressif__zlib.a +[991/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngtest.c.obj +[992/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwtran.c.obj +[993/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngget.c.obj +[994/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_mem_caps.c.obj +[995/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngset.c.obj +[996/1343] Building C object esp-idf/ts_jsonpath/CMakeFiles/__idf_ts_jsonpath.dir/src/ts_jsonpath.c.obj +[997/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_networking_lwip.c.obj +[998/1343] Building C object esp-idf/espressif__esp_websocket_client/CMakeFiles/__idf_espressif__esp_websocket_client.dir/esp_websocket_client.c.obj +[999/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwrite.c.obj +[1000/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngwutil.c.obj +[1001/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent_win.c.obj +[1002/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns_console.c.obj +[1003/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/blowfish.c.obj +[1004/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/png.c.obj +[1005/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/bcrypt_pbkdf.c.obj +[1006/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngread.c.obj +[1007/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/agent.c.obj +[1008/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrutil.c.obj +[1009/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/comp.c.obj +[1010/1343] Building C object esp-idf/espressif__libpng/CMakeFiles/__idf_espressif__libpng.dir/libpng/pngrtran.c.obj +[1011/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/crypt.c.obj +[1012/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/global.c.obj +[1013/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/keepalive.c.obj +[1014/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/openssl.c.obj +[1015/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/hostkey.c.obj +[1016/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/libgcrypt.c.obj +[1017/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mac.c.obj +[1018/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/os400qc3.c.obj +[1019/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/knownhost.c.obj +[1020/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/misc.c.obj +[1021/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/channel.c.obj +[1022/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/pem.c.obj +[1023/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/mbedtls.c.obj +[1024/1343] Linking C static library esp-idf/ts_log/libts_log.a +[1025/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/scp.c.obj +[1026/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/packet.c.obj +[1027/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/version.c.obj +[1028/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/publickey.c.obj +[1029/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/transport.c.obj +[1030/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth_kbd_packet.c.obj +[1031/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/wincng.c.obj +[1032/1343] Linking C static library esp-idf/esp_https_server/libesp_https_server.a +[1033/1343] Linking C static library esp-idf/espressif__esp_websocket_client/libespressif__esp_websocket_client.a +[1034/1343] Linking C static library esp-idf/espressif__led_strip/libespressif__led_strip.a +[1035/1343] Building C object esp-idf/ts_mempool/CMakeFiles/__idf_ts_mempool.dir/src/ts_mempool.c.obj +[1036/1343] Linking C static library esp-idf/espressif__esp_jpeg/libespressif__esp_jpeg.a +[1037/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/session.c.obj +[1038/1343] Linking C static library esp-idf/ts_jsonpath/libts_jsonpath.a +[1039/1343] Building C object esp-idf/ts_service/CMakeFiles/__idf_ts_service.dir/src/ts_service.c.obj +[1040/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/kex.c.obj +[1041/1343] Linking C static library esp-idf/espressif__libpng/libespressif__libpng.a +[1042/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_nvs.c.obj +[1043/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_json.c.obj +[1044/1343] Linking C static library esp-idf/ts_mempool/libts_mempool.a +[1045/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_schemas.c.obj +[1046/1343] Linking C static library esp-idf/ts_service/libts_service.a +[1047/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_meta.c.obj +[1048/1343] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert_time.c.obj +[1049/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/userauth.c.obj +[1050/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config.c.obj +[1051/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_file.c.obj +[1052/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_auth.c.obj +[1053/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_security.c.obj +[1054/1343] Building C object esp-idf/ts_config/CMakeFiles/__idf_ts_config.dir/src/ts_config_module.c.obj +[1055/1343] Building C object esp-idf/ch405labs_esp_libssh2/CMakeFiles/__idf_ch405labs_esp_libssh2.dir/libssh2/src/sftp.c.obj +[1056/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_client.c.obj +[1057/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_scp.c.obj +[1058/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_shell.c.obj +[1059/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_crypto.c.obj +[1060/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_sftp.c.obj +[1061/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_known_hosts.c.obj +[1062/1343] Building C object esp-idf/ts_config_pack/CMakeFiles/__idf_ts_config_pack.dir/src/ts_config_pack.c.obj +[1063/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_port_forward.c.obj +[1064/1343] Building C object esp-idf/ts_cert/CMakeFiles/__idf_ts_cert.dir/src/ts_cert.c.obj +[1065/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_log_watch.c.obj +[1066/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_probe.c.obj +[1067/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_hosts_config.c.obj +[1068/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_keystore.c.obj +[1069/1343] Linking C static library esp-idf/ch405labs_esp_libssh2/libch405labs_esp_libssh2.a +[1070/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_compat.c.obj +[1071/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_commands_config.c.obj +[1072/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_store.c.obj +[1073/1343] Building C object esp-idf/espressif__mdns/CMakeFiles/__idf_espressif__mdns.dir/mdns.c.obj +[1074/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_runner.c.obj +[1075/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_freertos.c.obj +[1076/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_codec.c.obj +[1077/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_variable.c.obj +[1078/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_cache.c.obj +[1079/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_automation.c.obj +[1080/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_utils_memory.c.obj +[1081/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity_port_esp32.c.obj +[1082/1343] Linking C static library esp-idf/espressif__mdns/libespressif__mdns.a +[1083/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/port/esp/unity_utils_memory_esp.c.obj +[1084/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/constants.pb-c.c.obj +[1085/1343] Building C object esp-idf/unity/CMakeFiles/__idf_unity.dir/unity/src/unity.c.obj +[1086/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/session.pb-c.c.obj +[1087/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec1.pb-c.c.obj +[1088/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec2.pb-c.c.obj +[1089/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/proto-c/sec0.pb-c.c.obj +[1090/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/common/protocomm.c.obj +[1091/1343] Building C object esp-idf/ts_security/CMakeFiles/__idf_ts_security.dir/src/ts_ssh_service.c.obj +[1092/1343] Linking C static library esp-idf/ts_config/libts_config.a +[1093/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security0.c.obj +[1094/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_console.c.obj +[1095/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/transports/protocomm_httpd.c.obj +[1096/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp_mpi.c.obj +[1097/1343] Linking C static library esp-idf/ts_config_pack/libts_config_pack.a +[1098/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/host_file_io.c.obj +[1099/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace_util.c.obj +[1100/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/crypto/srp6a/esp_srp.c.obj +[1101/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/app_trace.c.obj +[1102/1343] Linking C static library esp-idf/unity/libunity.a +[1103/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security1.c.obj +[1104/1343] Building C object esp-idf/app_trace/CMakeFiles/__idf_app_trace.dir/port/port_uart.c.obj +[1105/1343] Building C object esp-idf/protobuf-c/CMakeFiles/__idf_protobuf-c.dir/protobuf-c/protobuf-c/protobuf-c.c.obj +[1106/1343] Linking C static library esp-idf/ts_cert/libts_cert.a +[1107/1343] Building C object esp-idf/cmock/CMakeFiles/__idf_cmock.dir/CMock/src/cmock.c.obj +[1108/1343] Building C object esp-idf/protocomm/CMakeFiles/__idf_protocomm.dir/src/security/security2.c.obj +[1109/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp_share_ctrl.c.obj +[1110/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/esp_cam_ctlr.c.obj +[1111/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_gdma.c.obj +[1112/1343] Linking C static library esp-idf/protobuf-c/libprotobuf-c.a +[1113/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidd.c.obj +[1114/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hid_common.c.obj +[1115/1343] Linking C static library esp-idf/ts_security/libts_security.a +[1116/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_common.c.obj +[1117/1343] Building C object esp-idf/esp_hid/CMakeFiles/__idf_esp_hid.dir/src/esp_hidh.c.obj +[1118/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_io.c.obj +[1119/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_rule_engine.c.obj +[1120/1343] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/common/touch_sens_common.c.obj +[1121/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ops.c.obj +[1122/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_nt35510.c.obj +[1123/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_ssd1306.c.obj +[1124/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/src/esp_lcd_panel_st7789.c.obj +[1125/1343] Building C object esp-idf/esp_driver_touch_sens/CMakeFiles/__idf_esp_driver_touch_sens.dir/hw_ver2/touch_version_specific.c.obj +[1126/1343] Building C object esp-idf/esp_driver_cam/CMakeFiles/__idf_esp_driver_cam.dir/dvp/src/esp_cam_ctlr_dvp_cam.c.obj +[1127/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_init.c.obj +[1128/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v1.c.obj +[1129/1343] Linking C static library esp-idf/protocomm/libprotocomm.a +[1130/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_source_manager.c.obj +[1131/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i2c/esp_lcd_panel_io_i2c_v2.c.obj +[1132/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_handler.c.obj +[1133/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_sha.c.obj +[1134/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_common.c.obj +[1135/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/proto-c/esp_local_ctrl.pb-c.c.obj +[1136/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/spi/esp_lcd_panel_io_spi.c.obj +[1137/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_crc.c.obj +[1138/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl.c.obj +[1139/1343] Building C object esp-idf/esp_local_ctrl/CMakeFiles/__idf_esp_local_ctrl.dir/src/esp_local_ctrl_transport_httpd.c.obj +[1140/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_binary.c.obj +[1141/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_elf.c.obj +[1142/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_flash.c.obj +[1143/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/core_dump_uart.c.obj +[1144/1343] Building C object esp-idf/ts_automation/CMakeFiles/__idf_ts_automation.dir/src/ts_action_manager.c.obj +[1145/1343] Building C object esp-idf/espcoredump/CMakeFiles/__idf_espcoredump.dir/src/port/xtensa/core_dump_port.c.obj +[1146/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_access.c.obj +[1147/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_masks.c.obj +[1148/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/i80/esp_lcd_panel_io_i80.c.obj +[1149/1343] Building C object esp-idf/perfmon/CMakeFiles/__idf_perfmon.dir/xtensa_perfmon_apis.c.obj +[1150/1343] Building C object esp-idf/nvs_sec_provider/CMakeFiles/__idf_nvs_sec_provider.dir/nvs_sec_provider.c.obj +[1151/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/platform_esp32_idf.c.obj +[1152/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_msg.c.obj +[1153/1343] Linking C static library esp-idf/ts_automation/libts_automation.a +[1154/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/lib/mqtt_outbox.c.obj +[1155/1343] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_utils.c.obj +[1156/1343] Building C object esp-idf/rt/CMakeFiles/__idf_rt.dir/FreeRTOS_POSIX_mqueue.c.obj +[1157/1343] Generating ../../lpmu-agx-network-setup.tar.gz.S +[1158/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_private.c.obj +[1159/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_button.c.obj +[1160/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_matrix.c.obj +[1161/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_helpers.c.obj +[1162/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hub.c.obj +[1163/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_element.c.obj +[1164/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_phy.c.obj +[1165/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api.c.obj +[1166/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/enum.c.obj +[1167/1343] Building C object esp-idf/touch_element/CMakeFiles/__idf_touch_element.dir/touch_slider.c.obj +[1168/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usb_host.c.obj +[1169/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config.c.obj +[1170/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/usbh.c.obj +[1171/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_config_pack.c.obj +[1172/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_system.c.obj +[1173/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_network.c.obj +[1174/1343] Building C object esp-idf/esp_lcd/CMakeFiles/__idf_esp_lcd.dir/rgb/esp_lcd_panel_rgb.c.obj +[1175/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_fan.c.obj +[1176/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_service.c.obj +[1177/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_power.c.obj +[1178/1343] Building C object esp-idf/usb/CMakeFiles/__idf_usb.dir/hcd_dwc.c.obj +[1179/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_storage.c.obj +[1180/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_gpio.c.obj +[1181/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_temp.c.obj +[1182/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_monitor.c.obj +[1183/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_nat.c.obj +[1184/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_dhcp.c.obj +[1185/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_hosts.c.obj +[1186/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_wifi.c.obj +[1187/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_device.c.obj +[1188/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_key.c.obj +[1189/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_led.c.obj +[1190/1343] Building C object esp-idf/mqtt/CMakeFiles/__idf_mqtt.dir/esp-mqtt/mqtt_client.c.obj +[1191/1343] Building ASM object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/__/__/lpmu-agx-network-setup.tar.gz.S.obj +[1192/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_lpmu_access.c.obj +[1193/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_time.c.obj +[1194/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_auth.c.obj +[1195/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_sftp.c.obj +[1196/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_log.c.obj +[1197/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ui.c.obj +[1198/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_api.c.obj +[1199/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_cert.c.obj +[1200/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui.c.obj +[1201/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https_auth.c.obj +[1202/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_i18n.c.obj +[1203/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_api.c.obj +[1204/1343] Building C object esp-idf/ts_https/CMakeFiles/__idf_ts_https.dir/src/ts_https.c.obj +[1205/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_args.c.obj +[1206/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_operation.c.obj +[1207/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ota.c.obj +[1208/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console.c.obj +[1209/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_console_builtin.c.obj +[1210/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_ssh.c.obj +[1211/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_subscriptions.c.obj +[1212/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/src/ts_script.c.obj +[1213/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_ws_transport.c.obj +[1214/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_auto.c.obj +[1215/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/linenoise/linenoise.c.obj +[1216/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_monitor.c.obj +[1217/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_config.c.obj +[1218/1343] Building C object esp-idf/ts_webui/CMakeFiles/__idf_ts_webui.dir/src/ts_webui_ws.c.obj +[1219/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_device.c.obj +[1220/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_gpio.c.obj +[1221/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fan.c.obj +[1222/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_dhcp.c.obj +[1223/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_fs.c.obj +[1224/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_nat.c.obj +[1225/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_net.c.obj +[1226/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_register.c.obj +[1227/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_key.c.obj +[1228/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_hosts.c.obj +[1229/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ota.c.obj +[1230/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_power.c.obj +[1231/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_service.c.obj +[1232/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_pki.c.obj +[1233/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_storage.c.obj +[1234/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_sftp.c.obj +[1235/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_system.c.obj +[1236/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_voltprot.c.obj +[1237/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_version.c.obj +[1238/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_temp.c.obj +[1239/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_rollback.c.obj +[1240/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_wifi.c.obj +[1241/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota.c.obj +[1242/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_sdcard.c.obj +[1243/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_recovery.c.obj +[1244/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_ssh.c.obj +[1245/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net.c.obj +[1246/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_wifi.c.obj +[1247/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_eth.c.obj +[1248/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led.c.obj +[1249/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_driver.c.obj +[1250/1343] Building C object esp-idf/ts_api/CMakeFiles/__idf_ts_api.dir/src/ts_api_automation.c.obj +[1251/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_https.c.obj +[1252/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_nat.c.obj +[1253/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_time_sync.c.obj +[1254/1343] Building C object esp-idf/ts_console/CMakeFiles/__idf_ts_console.dir/commands/ts_cmd_led.c.obj +[1255/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_http_server.c.obj +[1256/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_www.c.obj +[1257/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color.c.obj +[1258/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_layer.c.obj +[1259/1343] Linking C static library esp-idf/ts_api/libts_api.a +[1260/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_qrcode.c.obj +[1261/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_net_manager.c.obj +[1262/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_https_server.c.obj +[1263/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_drivers.c.obj +[1264/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_color_correction.c.obj +[1265/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_effect.c.obj +[1266/1343] Linking C static library esp-idf/ts_https/libts_https.a +[1267/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_animation.c.obj +[1268/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_font.c.obj +[1269/1343] Building C object esp-idf/ts_ota/CMakeFiles/__idf_ts_ota.dir/src/ts_ota_download.c.obj +[1270/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_usb_mux.c.obj +[1271/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_preset.c.obj +[1272/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_text.c.obj +[1273/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/qrcodegen/qrcodegen.c.obj +[1274/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power.c.obj +[1275/1343] Linking C static library esp-idf/ts_webui/libts_webui.a +[1276/1343] Building C object esp-idf/ts_net/CMakeFiles/__idf_ts_net.dir/src/ts_dhcp_server.c.obj +[1277/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_monitor.c.obj +[1278/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_hal.c.obj +[1279/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_fan.c.obj +[1280/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_gpio.c.obj +[1281/1343] Performing configure step for 'bootloader' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-xterm-final/sdkconfig +-- Compiler supported targets: xtensa-esp-elf +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Bootloader project name: "bootloader" version: 1 +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.rom.ld +-- Components: bootloader bootloader_support efuse esp_app_format esp_bootloader_format esp_common esp_hw_support esp_rom esp_security esp_system esptool_py freertos hal log main micro-ecc newlib partition_table soc spi_flash xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/components/micro-ecc /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +-- Configuring done (4.7s) +-- Generating done (0.2s) +-- Build files have been written to: /tmp/tianshan-xterm-final/build/bootloader +[1282/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_i2c.c.obj +[1283/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/platform/esp32s3/ts_platform_s3.c.obj +[1284/1343] Linking C static library esp-idf/ts_console/libts_console.a +[1285/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pwm.c.obj +[1286/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_temp_source.c.obj +[1287/1343] Building C object esp-idf/ts_led/CMakeFiles/__idf_ts_led.dir/src/ts_led_image.c.obj +[1288/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_spi.c.obj +[1289/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_uart.c.obj +[1290/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_pin_manager.c.obj +[1291/1343] Building C object esp-idf/ts_hal/CMakeFiles/__idf_ts_hal.dir/src/ts_adc.c.obj +[1292/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_power_policy.c.obj +[1293/1343] Linking C static library esp-idf/ts_ota/libts_ota.a +[1294/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_device_ctrl.c.obj +[1295/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_spiffs.c.obj +[1296/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_config.c.obj +[1297/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_ctrl.c.obj +[1298/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/handlers.c.obj +[1299/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_ctrl.pb-c.c.obj +[1300/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_constants.pb-c.c.obj +[1301/1343] Linking C static library esp-idf/ts_net/libts_net.a +[1302/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_config.pb-c.c.obj +[1303/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_console.c.obj +[1304/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/proto-c/wifi_scan.pb-c.c.obj +[1305/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/wifi_scan.c.obj +[1306/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/scheme_softap.c.obj +[1307/1343] Linking C static library esp-idf/cmock/libcmock.a +[1308/1343] Linking C static library esp-idf/app_trace/libapp_trace.a +[1309/1343] Linking C static library esp-idf/esp_driver_cam/libesp_driver_cam.a +[1310/1343] Linking C static library esp-idf/esp_driver_touch_sens/libesp_driver_touch_sens.a +[1311/1343] Linking C static library esp-idf/esp_hid/libesp_hid.a +[1312/1343] Linking C static library esp-idf/esp_local_ctrl/libesp_local_ctrl.a +[1313/1343] Linking C static library esp-idf/esp_lcd/libesp_lcd.a +[1314/1343] Linking C static library esp-idf/ts_led/libts_led.a +[1315/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_core_init.c.obj +[1316/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage_sd.c.obj +[1317/1343] Building C object esp-idf/ts_storage/CMakeFiles/__idf_ts_storage.dir/src/ts_storage.c.obj +[1318/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/main.c.obj +[1319/1343] Building C object esp-idf/ts_drivers/CMakeFiles/__idf_ts_drivers.dir/src/ts_compute_monitor.c.obj +[1320/1343] Linking C static library esp-idf/espcoredump/libespcoredump.a +[1321/1343] Linking C static library esp-idf/mqtt/libmqtt.a +[1322/1343] Linking C static library esp-idf/nvs_sec_provider/libnvs_sec_provider.a +[1323/1343] Linking C static library esp-idf/perfmon/libperfmon.a +[1324/1343] Linking C static library esp-idf/rt/librt.a +[1325/1343] Linking C static library esp-idf/touch_element/libtouch_element.a +[1326/1343] Linking C static library esp-idf/usb/libusb.a +[1327/1343] Linking C static library esp-idf/ts_drivers/libts_drivers.a +[1328/1343] Linking C static library esp-idf/ts_hal/libts_hal.a +[1329/1343] Linking C static library esp-idf/ts_storage/libts_storage.a +[1330/1343] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/ts_services.c.obj +[1331/1343] Building C object esp-idf/ts_pki_client/CMakeFiles/__idf_ts_pki_client.dir/src/ts_pki_client.c.obj +[1332/1343] Linking C static library esp-idf/ts_pki_client/libts_pki_client.a +[1333/1343] Building C object esp-idf/wifi_provisioning/CMakeFiles/__idf_wifi_provisioning.dir/src/manager.c.obj +[1334/1343] Linking C static library esp-idf/main/libmain.a +[1335/1343] Linking C static library esp-idf/wifi_provisioning/libwifi_provisioning.a +[1336/1343] Performing build step for 'bootloader' +[1/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/util.c.obj +[2/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[3/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_timestamp.c.obj +[4/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/noos/log_lock.c.obj +[5/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[6/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[7/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[8/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[9/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[10/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[11/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[12/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[13/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[14/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[15/123] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[16/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[17/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[18/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[19/123] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[20/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[21/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[22/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[23/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[24/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[25/123] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[26/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[27/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[28/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[29/123] Linking C static library esp-idf/log/liblog.a +[30/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[31/123] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[32/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[33/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[34/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[35/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[36/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[37/123] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[38/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[39/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[40/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[41/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[42/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[43/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[44/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[45/123] Linking C static library esp-idf/esp_rom/libesp_rom.a +[46/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[47/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[48/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[49/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[50/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[51/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[52/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[53/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_loader.c.obj +[54/123] Linking C static library esp-idf/esp_common/libesp_common.a +[55/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console_loader.c.obj +[56/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[57/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_soc.c.obj +[58/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_console.c.obj +[59/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[60/123] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[61/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_panic.c.obj +[62/123] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[63/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[64/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[65/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[66/123] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[67/123] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[68/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_init.c.obj +[69/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/bootloader_esp32s3.c.obj +[70/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[71/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[72/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[73/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[74/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[75/123] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[76/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[77/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[78/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[79/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[80/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[81/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[82/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[83/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[84/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[85/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[86/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[87/123] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[88/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[89/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[90/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[91/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[92/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[93/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[94/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[95/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[96/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[97/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[98/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[99/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[100/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[101/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[102/123] Generating project_elf_src_esp32s3.c +[103/123] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[104/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/eri.c.obj +[105/123] Linking C static library esp-idf/esp_system/libesp_system.a +[106/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[107/123] Building C object esp-idf/xtensa/CMakeFiles/__idf_xtensa.dir/xt_trax.c.obj +[108/123] Building C object CMakeFiles/bootloader.elf.dir/project_elf_src_esp32s3.c.obj +[109/123] Building C object esp-idf/main/CMakeFiles/__idf_main.dir/bootloader_start.c.obj +[110/123] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[111/123] Linking C static library esp-idf/efuse/libefuse.a +[112/123] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[113/123] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[114/123] Building C object esp-idf/micro-ecc/CMakeFiles/__idf_micro-ecc.dir/uECC_verify_antifault.c.obj +[115/123] Linking C static library esp-idf/spi_flash/libspi_flash.a +[116/123] Linking C static library esp-idf/hal/libhal.a +[117/123] Linking C static library esp-idf/micro-ecc/libmicro-ecc.a +[118/123] Linking C static library esp-idf/soc/libsoc.a +[119/123] Linking C static library esp-idf/xtensa/libxtensa.a +[120/123] Linking C static library esp-idf/main/libmain.a +[121/123] Linking C executable bootloader.elf +[122/123] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-xterm-final/build/bootloader/bootloader.bin +[123/123] cd /tmp/tianshan-xterm-final/build/bootloader/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /tmp/tianshan-xterm-final/build/bootloader/bootloader.bin +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[1337/1343] No install step for 'bootloader' +[1338/1343] Completed 'bootloader' +[1339/1343] Generating esp-idf/esp_system/ld/sections.ld +[1340/1343] Building C object CMakeFiles/TianShanOS.elf.dir/project_elf_src_esp32s3.c.obj +[1341/1343] Linking CXX executable TianShanOS.elf +[1342/1343] Generating binary image from built executable +esptool.py v4.12.dev2 +Creating esp32s3 image... +Merged 2 ELF sections +Successfully created esp32s3 image. +Generated /tmp/tianshan-xterm-final/build/TianShanOS.bin +[1343/1343] cd /tmp/tianshan-xterm-final/build/esp-idf/esptool_py && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 partition --type app /tmp/tianshan-xterm-final/build/partition_table/partition-table.bin /tmp/tianshan-xterm-final/build/TianShanOS.bin +TianShanOS.bin binary size 0x215120 bytes. Smallest app partition is 0x300000 bytes. 0xeaee0 bytes (31%) free. + +Project build complete. To flash, run: + idf.py flash +or + idf.py -p PORT flash +or + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 ../../../private/tmp/tianshan-xterm-final/build/bootloader/bootloader.bin 0x8000 ../../../private/tmp/tianshan-xterm-final/build/partition_table/partition-table.bin 0x16000 ../../../private/tmp/tianshan-xterm-final/build/ota_data_initial.bin 0x20000 ../../../private/tmp/tianshan-xterm-final/build/TianShanOS.bin 0x6a0000 ../../../private/tmp/tianshan-xterm-final/build/www.bin +or from the "/private/tmp/tianshan-xterm-final/build" directory + python -m esptool --chip esp32s3 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args" diff --git a/docs/repair/xterm-local/changes.patch b/docs/repair/xterm-local/changes.patch new file mode 100644 index 0000000..7113015 --- /dev/null +++ b/docs/repair/xterm-local/changes.patch @@ -0,0 +1,149 @@ +diff --git a/components/ts_webui/web/index.html b/components/ts_webui/web/index.html +index 59265c7..eea293c 100644 +--- a/components/ts_webui/web/index.html ++++ b/components/ts_webui/web/index.html +@@ -41,9 +41,9 @@ + .modal-content{background:var(--bg-card);border-radius:var(--radius-lg);max-width:600px;width:95%;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg)} + + +- +- +- ++ ++ ++ + + + +@@ -247,7 +247,7 @@ + + + +- +- +- +- +- ++ ++ ++ ++ ++ + + +diff --git a/components/ts_webui/web/js/terminal.js b/components/ts_webui/web/js/terminal.js +index 8fb1240..b1783eb 100644 +--- a/components/ts_webui/web/js/terminal.js ++++ b/components/ts_webui/web/js/terminal.js +@@ -4,7 +4,7 @@ + */ + + /** +- * 按需加载 xterm.js 及其插件(从 CDN) ++ * 按需加载 xterm.js 及其插件(设备本地资源) + * 仅在首次打开终端页面时触发,后续调用直接返回 + */ + const _xtermReady = (function() { +@@ -30,9 +30,9 @@ const _xtermReady = (function() { + } + return function ensureXtermLoaded() { + if (_promise) return _promise; +- _promise = loadResource('https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css', true) +- .then(() => loadResource('https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js', false)) +- .then(() => loadResource('https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js', false)) ++ _promise = loadResource('/vendor/xterm/xterm.css?v=' + encodeURIComponent(window.TS_ASSET_VERSION), true) ++ .then(() => loadResource('/vendor/xterm/xterm.min.js?v=' + encodeURIComponent(window.TS_ASSET_VERSION), false)) ++ .then(() => loadResource('/vendor/xterm/fit.min.js?v=' + encodeURIComponent(window.TS_ASSET_VERSION), false)) + .catch(error => { _promise = null; throw error; }); + return _promise; + }; +@@ -70,7 +70,7 @@ class WebTerminal { + return false; + } + +- // 按需加载 xterm.js(首次访问终端页面时从 CDN 拉取) ++ // 按需加载 xterm.js(首次访问终端页面时从设备加载) + try { await _xtermReady(); } + catch (error) { + if (this.destroyed) return false; +diff --git a/tests/prompts/browser.test.cjs b/tests/prompts/browser.test.cjs +index e452f44..5ff034e 100644 +--- a/tests/prompts/browser.test.cjs ++++ b/tests/prompts/browser.test.cjs +@@ -71,7 +71,7 @@ test('delayed language package and rapid switches keep the latest requested lang + }finally{release();await context.close();} + }); + test('terminal resource failure presents retry; a rejected cached promise is not reused',async()=>{ +- const {page,context,errors}=await pageFor('en-US');let attempts=0; ++ const {page,context,errors}=await pageFor('en-US',async(route,u)=>{if(u.pathname.startsWith('/vendor/')){await route.abort();return true;}return false;});let attempts=0; + try{await page.goto(base);await page.waitForFunction(()=>i18n.isReady()); + page.on('request',r=>{if(r.url().includes('xterm.css'))attempts++;}); + await page.evaluate(()=>{closeLoginModal();return loadTerminalPage();}); +@@ -118,15 +118,12 @@ test('failed language switch preserves the loaded language; retry clears failure + }finally{await context.close();} + }); + test('terminal can initialize after failed resource load using newly served resources',async()=>{ +- const {page,context,errors}=await pageFor('en-US'); ++ let fail=true; ++ const {page,context,errors}=await pageFor('en-US',async(route,u)=>{if(fail&&u.pathname.startsWith('/vendor/')){await route.abort();return true;}return false;}); + try{await page.goto(base);await page.waitForFunction(()=>i18n.isReady());await page.evaluate(()=>{closeLoginModal();return loadTerminalPage();}); +- await page.route('https://cdn.jsdelivr.net/**',async route=>{ +- const url=route.request().url();let body=''; +- if(url.includes('xterm.min.js')) body=`window.Terminal=class {constructor(){this.cols=80;this.rows=24;}open(el){el.replaceChildren();el.dataset.terminalReady='yes';}onData(){}loadAddon(){}write(){}writeln(){}focus(){}dispose(){}};`; +- if(url.includes('xterm-addon-fit'))body='window.FitAddon={FitAddon:class {fit(){}}};'; +- await route.fulfill({contentType:url.endsWith('.css')?'text/css':'application/javascript',body}); +- }); +- await page.locator('#terminal-container button').click();await page.waitForSelector('#terminal-container[data-terminal-ready="yes"]'); ++ assert.equal(await page.locator('#terminal-container button').count(),1); ++ fail=false;await page.locator('#terminal-container button').click();await page.waitForSelector('#terminal-container .xterm'); ++ assert(await page.evaluate(()=>webTerminal.terminal instanceof Terminal&&!!webTerminal.fitAddon)); + assert.equal(await page.locator('#terminal-container button').count(),0);assert.deepEqual(errors,[]); + }finally{await context.close();} + }); +diff --git a/tests/prompts/package.json b/tests/prompts/package.json +index 7ee8d1f..fb6290b 100644 +--- a/tests/prompts/package.json ++++ b/tests/prompts/package.json +@@ -6,7 +6,8 @@ + }, + "scripts": { + "test": "cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs", +- "test:browser": "cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs" ++ "test:browser": "cd ../.. && node --test tests/prompts/browser.test.cjs tests/prompts/ownership.browser.test.cjs", ++ "test:xterm": "cd ../.. && node --test tests/prompts/xterm-vendor.test.cjs tests/prompts/xterm-offline.test.cjs" + }, + "devDependencies": { + "acorn": "8.16.0", +diff --git a/tools/minify_web.py b/tools/minify_web.py +index 0c1bd9a..3e8d510 100644 +--- a/tools/minify_web.py ++++ b/tools/minify_web.py +@@ -123,6 +123,9 @@ def process_directory(web_dir: str) -> None: + + # 处理 JS 文件 + for filepath in glob.glob(os.path.join(web_dir, '**', '*.js'), recursive=True): ++ # Preserve third-party release bytes; gzip still runs below. ++ if os.path.relpath(filepath, web_dir).split(os.sep)[0] == 'vendor': ++ continue + original_size = os.path.getsize(filepath) + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() +@@ -141,6 +144,9 @@ def process_directory(web_dir: str) -> None: + + # 处理 CSS 文件 + for filepath in glob.glob(os.path.join(web_dir, '**', '*.css'), recursive=True): ++ # Preserve third-party release bytes; gzip still runs below. ++ if os.path.relpath(filepath, web_dir).split(os.sep)[0] == 'vendor': ++ continue + original_size = os.path.getsize(filepath) + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() diff --git a/docs/repair/xterm-local/cross-en.json b/docs/repair/xterm-local/cross-en.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/xterm-local/cross-en.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/xterm-local/cross-en.txt b/docs/repair/xterm-local/cross-en.txt new file mode 100644 index 0000000..7c3e1b4 --- /dev/null +++ b/docs/repair/xterm-local/cross-en.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node en-US: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/xterm-local/cross-zh.json b/docs/repair/xterm-local/cross-zh.json new file mode 100644 index 0000000..3899237 --- /dev/null +++ b/docs/repair/xterm-local/cross-zh.json @@ -0,0 +1,869 @@ +{ + "records": [ + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 0, + "state": 0, + "writes": 0, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 0, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 1, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "frame": { + "type": "power_event", + "state": "LOW_VOLTAGE", + "voltage": 10.5, + "countdown": 30, + "protection_count": 0, + "event": "low_voltage" + }, + "fd": 2, + "bytes": "{\"type\":\"power_event\",\"state\":\"LOW_VOLTAGE\",\"voltage\":10.5,\"countdown\":30,\"protection_count\":0,\"event\":\"low_voltage\"}" + }, + { + "identity": 1, + "state": 2, + "writes": 1, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 1, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Invalid SSH control parameters" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Invalid SSH control parameters\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH control request failed; input was not replayed" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH control request failed; input was not replayed\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 19, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 17, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 20, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "This connection does not own an active SSH session" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"This connection does not own an active SSH session\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 2, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 23, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Another SSH session is active" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Another SSH session is active\"}" + }, + { + "identity": 2, + "state": 2, + "writes": 2, + "live": 21, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "disconnecting", + "message": "Closing SSH session..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"disconnecting\",\"message\":\"Closing SSH session...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "done", + "code": 0 + }, + "fd": 1, + "bytes": "{\"type\":\"done\",\"code\":0}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Not a terminal session" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Not a terminal session\"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "connected", + "message": "Terminal session started", + "prompt": "tianshan> " + }, + "fd": 1, + "bytes": "{\"type\":\"connected\",\"message\":\"Terminal session started\",\"prompt\":\"tianshan> \"}" + }, + { + "identity": 2, + "state": 0, + "writes": 2, + "live": 8, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH channel failed; remote result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH channel failed; remote result is not confirmed\"}" + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 3, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 4, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 4, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "Failed to open shell" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"Failed to open shell\"}" + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 19, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 5, + "state": 0, + "writes": 2, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "SSH request rejected" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"SSH request rejected\"}" + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 2, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 6, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "error", + "message": "Unsupported SSH signal" + }, + "fd": 1, + "bytes": "{\"type\":\"error\",\"message\":\"Unsupported SSH signal\"}" + }, + { + "frame": { + "type": "ssh_output", + "data": "last output" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_output\",\"data\":\"last output\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "closed", + "message": "SSH session closed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"closed\",\"message\":\"SSH session closed\"}" + }, + { + "identity": 6, + "state": 0, + "writes": 3, + "live": 11, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "connecting", + "message": "Connecting to SSH server..." + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connecting\",\"message\":\"Connecting to SSH server...\"}" + }, + { + "frame": { + "type": "ssh_status", + "status": "connected", + "message": "SSH shell ready" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"connected\",\"message\":\"SSH shell ready\"}" + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 26, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 3, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 18, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 2, + "writes": 4, + "live": 13, + "channels": 1, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "identity": 7, + "state": 5, + "writes": 4, + "live": 8, + "channels": 0, + "refs": 1, + "preparing": 0, + "unsettled": 0 + }, + { + "frame": { + "type": "ssh_status", + "status": "error", + "message": "SSH output delivery incomplete; remote command result is not confirmed" + }, + "fd": 1, + "bytes": "{\"type\":\"ssh_status\",\"status\":\"error\",\"message\":\"SSH output delivery incomplete; remote command result is not confirmed\"}" + }, + { + "identity": 7, + "state": 0, + "writes": 4, + "live": 6, + "channels": 0, + "refs": 0, + "preparing": 0, + "unsettled": 0 + }, + { + "finished": true + } + ], + "stderr": "tests/ws_subscriptions/test_project.c:42:133: warning: format specifies type 'unsigned int' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]\n 42 | printf(\"{\\\"identity\\\":%u,\\\"state\\\":%d,\\\"writes\\\":%d,\\\"live\\\":%u,\\\"channels\\\":%d,\\\"refs\\\":%u,\\\"preparing\\\":%u,\\\"unsettled\\\":%u}\\n\",st.identity,st.phase,driver_writes,live_allocations,driver_channels,st.refs,st.preparing,st.unsettled);fflush(stdout);cJSON_Delete(j);\n | ~~ ^~~~~~~~~~~\n | %llu\n1 warning generated.\n", + "exit": 0 +} \ No newline at end of file diff --git a/docs/repair/xterm-local/cross-zh.txt b/docs/repair/xterm-local/cross-zh.txt new file mode 100644 index 0000000..4699bd2 --- /dev/null +++ b/docs/repair/xterm-local/cross-zh.txt @@ -0,0 +1,2 @@ +PASS J1 C power event -> actual JS -> original SSH input -> normal exit and channel cleanup +PASS Node zh-CN: actual C frames + JS dispatcher + next C requests; recoverable/fatal/start/EOF/owner/encoding/socket paths; C resources zero diff --git a/docs/repair/xterm-local/flasher_args.json b/docs/repair/xterm-local/flasher_args.json new file mode 100644 index 0000000..0e2ffeb --- /dev/null +++ b/docs/repair/xterm-local/flasher_args.json @@ -0,0 +1,28 @@ +{ + "write_flash_args" : [ "--flash_mode", "dio", + "--flash_size", "16MB", + "--flash_freq", "80m" ], + "flash_settings" : { + "flash_mode": "dio", + "flash_size": "16MB", + "flash_freq": "80m" + }, + "flash_files" : { + "0x0" : "bootloader/bootloader.bin", + "0x20000" : "TianShanOS.bin", + "0x8000" : "partition_table/partition-table.bin", + "0x16000" : "ota_data_initial.bin", + "0x6a0000" : "www.bin" + }, + "bootloader" : { "offset" : "0x0", "file" : "bootloader/bootloader.bin", "encrypted" : "false" }, + "app" : { "offset" : "0x20000", "file" : "TianShanOS.bin", "encrypted" : "false" }, + "partition-table" : { "offset" : "0x8000", "file" : "partition_table/partition-table.bin", "encrypted" : "false" }, + "otadata" : { "offset" : "0x16000", "file" : "ota_data_initial.bin", "encrypted" : "false" }, + "www" : { "offset" : "0x6a0000", "file" : "www.bin", "encrypted" : "false" }, + "extra_esptool_args" : { + "after" : "hard_reset", + "before" : "default_reset", + "stub" : true, + "chip" : "esp32s3" + } +} diff --git a/docs/repair/xterm-local/initial-build-path-failure.log b/docs/repair/xterm-local/initial-build-path-failure.log new file mode 100644 index 0000000..11e6659 --- /dev/null +++ b/docs/repair/xterm-local/initial-build-path-failure.log @@ -0,0 +1,1079 @@ +Executing action: all (aliases: build) +Running cmake in directory /private/tmp/tianshan-xterm-build/build +Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DPYTHON=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python -DESP_PLATFORM=1 -DSDKCONFIG=/tmp/tianshan-xterm-build/sdkconfig -DCCACHE_ENABLE=0 /Users/massif/TianshanOS"... +-- Found Python3: /opt/anaconda3/bin/python3.12 (found version "3.12.4") found components: Interpreter +-- IDF_TARGET is not set, guessed 'esp32s3' from sdkconfig '/tmp/tianshan-xterm-build/sdkconfig' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Component directory /Users/massif/TianshanOS/components/linenoise does not contain a CMakeLists.txt file. No component will be added +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +NOTICE: +Following dependencies have new versions available: +Dependency "espressif/libpng": "1.6.54" -> "1.6.58~2" +Dependency "espressif/mdns": "1.9.1" -> "1.13.1" +Dependency "espressif/zlib": "1.3.1" -> "1.3.2~1" +Consider running "idf.py update-dependencies" to update your lock file. +NOTICE: Processing 7 dependencies: +NOTICE: [1/7] espressif/esp_jpeg (1.3.1) +NOTICE: [2/7] espressif/esp_websocket_client (1.5.0) +NOTICE: [3/7] espressif/led_strip (3.0.3) +NOTICE: [4/7] espressif/libpng (1.6.54) +NOTICE: [5/7] espressif/mdns (1.9.1) +NOTICE: [6/7] espressif/zlib (1.3.1) +NOTICE: [7/7] idf (5.5.2) +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-xterm-build/sdkconfig +Loading defaults file /Users/massif/TianshanOS/sdkconfig.defaults... +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:54 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:56 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:64 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:66 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:82 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:84 line was updated to # === L2 NVS 加密配置(HMAC 方案)===n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:159 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:161 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:170 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:172 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:182 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:184 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:193 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:195 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:227 line was updated to # ============================================================================n +/var/folders/88/hzsgvlyj5xzghddxy9rk5_5m0000gn/T/kconfgen_tmpwsgg7d29:229 line was updated to # ============================================================================n +-- Compiler supported targets: xtensa-esp-elf +-- Found Python3: /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python (found version "3.12.4") found components: Interpreter +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS +-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS - Success +-- USING O3 +-- App "TianShanOS" version: 0.5.2+633bb94d.09281637 +-- Adding linker script /tmp/tianshan-xterm-build/build/esp-idf/esp_system/ld/memory.ld +-- Adding linker script /tmp/tianshan-xterm-build/build/esp-idf/esp_system/ld/sections.ld.in +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_master.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_50.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_smp.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_dtm.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_test.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ble_scan.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Web optimization enabled (minify + gzip) +-- Components: app_trace app_update bootloader bootloader_support bt ch405labs_esp_libssh2 cmock console cxx driver efuse esp-tls esp_adc esp_app_format esp_bootloader_format esp_coex esp_common esp_driver_ana_cmpr esp_driver_bitscrambler esp_driver_cam esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_isp esp_driver_jpeg esp_driver_ledc esp_driver_mcpwm esp_driver_parlio esp_driver_pcnt esp_driver_ppa esp_driver_rmt esp_driver_sdio esp_driver_sdm esp_driver_sdmmc esp_driver_sdspi esp_driver_spi esp_driver_touch_sens esp_driver_tsens esp_driver_twai esp_driver_uart esp_driver_usb_serial_jtag esp_eth esp_event esp_gdbstub esp_hid esp_http_client esp_http_server esp_https_ota esp_https_server esp_hw_support esp_lcd esp_local_ctrl esp_mm esp_netif esp_netif_stack esp_partition esp_phy esp_pm esp_psram esp_ringbuf esp_rom esp_security esp_system esp_timer esp_vfs_console esp_wifi espcoredump espressif__esp_jpeg espressif__esp_websocket_client espressif__led_strip espressif__libpng espressif__mdns espressif__zlib esptool_py fatfs freertos hal heap http_parser idf_test ieee802154 json log lwip main mbedtls mqtt newlib nvs_flash nvs_sec_provider openthread partition_table perfmon protobuf-c protocomm pthread rt sdmmc soc spi_flash spiffs tcp_transport touch_element ts_api ts_auth_layout ts_automation ts_cert ts_config ts_config_pack ts_console ts_core ts_drivers ts_event ts_hal ts_https ts_jsonpath ts_led ts_log ts_mempool ts_net ts_ota ts_pki_client ts_security ts_service ts_storage ts_webui ulp unity usb vfs wear_levelling wifi_provisioning wpa_supplicant xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/app_trace /Users/massif/esp/v5.5.2/esp-idf/components/app_update /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/bt /Users/massif/TianshanOS/components/ch405labs_esp_libssh2 /Users/massif/esp/v5.5.2/esp-idf/components/cmock /Users/massif/esp/v5.5.2/esp-idf/components/console /Users/massif/esp/v5.5.2/esp-idf/components/cxx /Users/massif/esp/v5.5.2/esp-idf/components/driver /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp-tls /Users/massif/esp/v5.5.2/esp-idf/components/esp_adc /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_coex /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ana_cmpr /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_bitscrambler /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_cam /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_dac /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gpio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_gptimer /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2c /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_i2s /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_isp /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_jpeg /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ledc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_mcpwm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_parlio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_pcnt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_ppa /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_rmt /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdio /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdm /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_sdspi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_spi /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_touch_sens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_tsens /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_twai /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_uart /Users/massif/esp/v5.5.2/esp-idf/components/esp_driver_usb_serial_jtag /Users/massif/esp/v5.5.2/esp-idf/components/esp_eth /Users/massif/esp/v5.5.2/esp-idf/components/esp_event /Users/massif/esp/v5.5.2/esp-idf/components/esp_gdbstub /Users/massif/esp/v5.5.2/esp-idf/components/esp_hid /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_client /Users/massif/esp/v5.5.2/esp-idf/components/esp_http_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_ota /Users/massif/esp/v5.5.2/esp-idf/components/esp_https_server /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_lcd /Users/massif/esp/v5.5.2/esp-idf/components/esp_local_ctrl /Users/massif/esp/v5.5.2/esp-idf/components/esp_mm /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif /Users/massif/esp/v5.5.2/esp-idf/components/esp_netif_stack /Users/massif/esp/v5.5.2/esp-idf/components/esp_partition /Users/massif/esp/v5.5.2/esp-idf/components/esp_phy /Users/massif/esp/v5.5.2/esp-idf/components/esp_pm /Users/massif/esp/v5.5.2/esp-idf/components/esp_psram /Users/massif/esp/v5.5.2/esp-idf/components/esp_ringbuf /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esp_timer /Users/massif/esp/v5.5.2/esp-idf/components/esp_vfs_console /Users/massif/esp/v5.5.2/esp-idf/components/esp_wifi /Users/massif/esp/v5.5.2/esp-idf/components/espcoredump /Users/massif/TianshanOS/managed_components/espressif__esp_jpeg /Users/massif/TianshanOS/managed_components/espressif__esp_websocket_client /Users/massif/TianshanOS/managed_components/espressif__led_strip /Users/massif/TianshanOS/managed_components/espressif__libpng /Users/massif/TianshanOS/managed_components/espressif__mdns /Users/massif/TianshanOS/managed_components/espressif__zlib /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/fatfs /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/heap /Users/massif/esp/v5.5.2/esp-idf/components/http_parser /Users/massif/esp/v5.5.2/esp-idf/components/idf_test /Users/massif/esp/v5.5.2/esp-idf/components/ieee802154 /Users/massif/esp/v5.5.2/esp-idf/components/json /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/lwip /Users/massif/TianshanOS/main /Users/massif/esp/v5.5.2/esp-idf/components/mbedtls /Users/massif/esp/v5.5.2/esp-idf/components/mqtt /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/nvs_flash /Users/massif/esp/v5.5.2/esp-idf/components/nvs_sec_provider /Users/massif/esp/v5.5.2/esp-idf/components/openthread /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/perfmon /Users/massif/esp/v5.5.2/esp-idf/components/protobuf-c /Users/massif/esp/v5.5.2/esp-idf/components/protocomm /Users/massif/esp/v5.5.2/esp-idf/components/pthread /Users/massif/esp/v5.5.2/esp-idf/components/rt /Users/massif/esp/v5.5.2/esp-idf/components/sdmmc /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/spiffs /Users/massif/esp/v5.5.2/esp-idf/components/tcp_transport /Users/massif/esp/v5.5.2/esp-idf/components/touch_element /Users/massif/TianshanOS/components/ts_api /Users/massif/TianshanOS/components/ts_auth_layout /Users/massif/TianshanOS/components/ts_automation /Users/massif/TianshanOS/components/ts_cert /Users/massif/TianshanOS/components/ts_core/ts_config /Users/massif/TianshanOS/components/ts_config_pack /Users/massif/TianshanOS/components/ts_console /Users/massif/TianshanOS/components/ts_core /Users/massif/TianshanOS/components/ts_drivers /Users/massif/TianshanOS/components/ts_core/ts_event /Users/massif/TianshanOS/components/ts_hal /Users/massif/TianshanOS/components/ts_https /Users/massif/TianshanOS/components/ts_jsonpath /Users/massif/TianshanOS/components/ts_led /Users/massif/TianshanOS/components/ts_core/ts_log /Users/massif/TianshanOS/components/ts_mempool /Users/massif/TianshanOS/components/ts_net /Users/massif/TianshanOS/components/ts_ota /Users/massif/TianshanOS/components/ts_pki_client /Users/massif/TianshanOS/components/ts_security /Users/massif/TianshanOS/components/ts_core/ts_service /Users/massif/TianshanOS/components/ts_storage /Users/massif/TianshanOS/components/ts_webui /Users/massif/esp/v5.5.2/esp-idf/components/ulp /Users/massif/esp/v5.5.2/esp-idf/components/unity /Users/massif/esp/v5.5.2/esp-idf/components/usb /Users/massif/esp/v5.5.2/esp-idf/components/vfs /Users/massif/esp/v5.5.2/esp-idf/components/wear_levelling /Users/massif/esp/v5.5.2/esp-idf/components/wifi_provisioning /Users/massif/esp/v5.5.2/esp-idf/components/wpa_supplicant /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- +-- ╔═══════════════════════════════════════════════════════════╗ +-- ║ TianShanOS v0.5.2+633bb94d.09281637 ║ +-- ║ ESP32 Rack Management Operating System ║ +-- ╚═══════════════════════════════════════════════════════════╝ +-- +-- Version: 0.5.2+633bb94d.09281637 +-- Major: 0 +-- Minor: 5 +-- Patch: 2 +-- Build: 633bb94d.09281637 +-- +-- Target: esp32s3 +-- Build type: +-- +-- Configuring done (7.4s) +-- Generating done (0.5s) +-- Build files have been written to: /tmp/tianshan-xterm-build/build +Running ninja in directory /private/tmp/tianshan-xterm-build/build +Executing "ninja all"... +[1/1343] Generating project_elf_src_esp32s3.c +[2/1343] Generating ../../ota_data_initial.bin +[3/1343] Generating /tmp/tianshan-xterm-build/build/esp-idf/esp_system/ld/memory.ld linker script... +[4/1343] Generating /tmp/tianshan-xterm-build/build/esp-idf/esp_system/ld/sections.ld.in linker script... +[5/1343] Copying web assets to build directory +[6/1343] Generating ../../partition_table/partition-table.bin +Partition table binary generated. Contents: +******************************************************************************* +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs,data,nvs,0x9000,48K, +nvs_keys,data,nvs_keys,0x15000,4K, +otadata,data,ota,0x16000,8K, +phy_init,data,phy,0x18000,4K, +ota_0,app,ota_0,0x20000,3M, +ota_1,app,ota_1,0x320000,3M, +storage,data,spiffs,0x620000,512K, +www,data,spiffs,0x6a0000,3M, +fatfs,data,fat,0x9a0000,64K, +******************************************************************************* +[7/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_utils.c.obj +[8/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_header.c.obj +[9/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/util/ctrl_sock.c.obj +[10/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_internal.c.obj +[11/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_uri.c.obj +[12/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_ws.c.obj +[13/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_sess.c.obj +[14/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/lib/http_auth.c.obj +[15/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_main.c.obj +[16/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_socks_proxy.c.obj +[17/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_txrx.c.obj +[18/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport.c.obj +[19/1343] Building C object esp-idf/esp_https_ota/CMakeFiles/__idf_esp_https_ota.dir/src/esp_https_ota.c.obj +[20/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/system_layer/esp_psram.c.obj +[21/1343] Building C object esp-idf/esp_http_server/CMakeFiles/__idf_esp_http_server.dir/src/httpd_parse.c.obj +[22/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ssl.c.obj +[23/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/xip_impl/mmu_psram_flash.c.obj +[24/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali.c.obj +[25/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp_adc_cal_common_legacy.c.obj +[26/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_cali_curve_fitting.c.obj +[27/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/esp32s3/curve_fitting_coefficients.c.obj +[28/1343] Building C object esp-idf/esp_psram/CMakeFiles/__idf_esp_psram.dir/esp32s3/esp_psram_impl_octal.c.obj +[29/1343] Linking C static library esp-idf/esp_https_ota/libesp_https_ota.a +[30/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/deprecated/esp32s3/esp_adc_cal_legacy.c.obj +[31/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_common.c.obj +[32/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/gdma/adc_dma.c.obj +[33/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_monitor.c.obj +[34/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp-tls-crypto/esp_tls_crypto.c.obj +[35/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_oneshot.c.obj +[36/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_platform_port.c.obj +[37/1343] Building C object esp-idf/tcp_transport/CMakeFiles/__idf_tcp_transport.dir/transport_ws.c.obj +[38/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_filter.c.obj +[39/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_error_capture.c.obj +[40/1343] Linking C static library esp-idf/esp_http_server/libesp_http_server.a +[41/1343] Building C object esp-idf/esp_adc/CMakeFiles/__idf_esp_adc.dir/adc_continuous.c.obj +[42/1343] Building C object esp-idf/esp_http_client/CMakeFiles/__idf_esp_http_client.dir/esp_http_client.c.obj +[43/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_dma_legacy.c.obj +[44/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/adc_legacy.c.obj +[45/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/sigma_delta_legacy.c.obj +[46/1343] Linking C static library esp-idf/esp_http_client/libesp_http_client.a +[47/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rtc_temperature_legacy.c.obj +[48/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/touch_sensor_common.c.obj +[49/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls.c.obj +[50/1343] Linking C static library esp-idf/tcp_transport/libtcp_transport.a +[51/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/pcnt_legacy.c.obj +[52/1343] Building C object esp-idf/esp-tls/CMakeFiles/__idf_esp-tls.dir/esp_tls_mbedtls.c.obj +[53/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/timer_legacy.c.obj +[54/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai.c.obj +[55/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/touch_sensor/esp32s3/touch_sensor.c.obj +[56/1343] Building C object esp-idf/http_parser/CMakeFiles/__idf_http_parser.dir/http_parser.c.obj +[57/1343] Linking C static library esp-idf/esp_psram/libesp_psram.a +[58/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/i2s_legacy.c.obj +[59/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/twai/twai.c.obj +[60/1343] Building C object esp-idf/esp_driver_twai/CMakeFiles/__idf_esp_driver_twai.dir/esp_twai_onchip.c.obj +[61/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_common.c.obj +[62/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/i2c/i2c.c.obj +[63/1343] Building C object esp-idf/esp_driver_sdm/CMakeFiles/__idf_esp_driver_sdm.dir/src/sdm.c.obj +[64/1343] Building C object esp-idf/esp_driver_tsens/CMakeFiles/__idf_esp_driver_tsens.dir/src/temperature_sensor.c.obj +[65/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder.c.obj +[66/1343] Linking C static library esp-idf/esp_adc/libesp_adc.a +[67/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/rmt_legacy.c.obj +[68/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_bytes.c.obj +[69/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_crc.c.obj +[70/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_common.c.obj +[71/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_slave.c.obj +[72/1343] Building C object esp-idf/driver/CMakeFiles/__idf_driver.dir/deprecated/mcpwm_legacy.c.obj +[73/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_copy.c.obj +[74/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_encoder_simple.c.obj +[75/1343] Linking C static library esp-idf/esp-tls/libesp-tls.a +[76/1343] Building C object esp-idf/esp_driver_i2c/CMakeFiles/__idf_esp_driver_i2c.dir/i2c_master.c.obj +[77/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_transaction.c.obj +[78/1343] Building C object esp-idf/esp_driver_ledc/CMakeFiles/__idf_esp_driver_ledc.dir/src/ledc.c.obj +[79/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_rx.c.obj +[80/1343] Building C object esp-idf/esp_driver_sdspi/CMakeFiles/__idf_esp_driver_sdspi.dir/src/sdspi_host.c.obj +[81/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_init.c.obj +[82/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_mmc.c.obj +[83/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_transaction.c.obj +[84/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_common.c.obj +[85/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sd_pwr_ctrl/sd_pwr_ctrl.c.obj +[86/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_io.c.obj +[87/1343] Linking C static library esp-idf/http_parser/libhttp_parser.a +[88/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_cmd.c.obj +[89/1343] Building C object esp-idf/esp_driver_rmt/CMakeFiles/__idf_esp_driver_rmt.dir/src/rmt_tx.c.obj +[90/1343] Building C object esp-idf/sdmmc/CMakeFiles/__idf_sdmmc.dir/sdmmc_sd.c.obj +[91/1343] Building C object esp-idf/esp_driver_sdmmc/CMakeFiles/__idf_esp_driver_sdmmc.dir/src/sdmmc_host.c.obj +[92/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_platform.c.obj +[93/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_std.c.obj +[94/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cmpr.c.obj +[95/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_com.c.obj +[96/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_tdm.c.obj +[97/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_fault.c.obj +[98/1343] Linking C static library esp-idf/driver/libdriver.a +[99/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_common.c.obj +[100/1343] Building C object esp-idf/esp_driver_i2s/CMakeFiles/__idf_esp_driver_i2s.dir/i2s_pdm.c.obj +[101/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub-entry.S.obj +[102/1343] Building ASM object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/xt_debugexception.S.obj +[103/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_cap.c.obj +[104/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_gen.c.obj +[105/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_sync.c.obj +[106/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_oper.c.obj +[107/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/packet.c.obj +[108/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub_transport.c.obj +[109/1343] Linking C static library esp-idf/esp_driver_twai/libesp_driver_twai.a +[110/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/port/xtensa/gdbstub_xtensa.c.obj +[111/1343] Building C object esp-idf/esp_driver_mcpwm/CMakeFiles/__idf_esp_driver_mcpwm.dir/src/mcpwm_timer.c.obj +[112/1343] Building C object esp-idf/esp_gdbstub/CMakeFiles/__idf_esp_gdbstub.dir/src/gdbstub.c.obj +[113/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/lib_printf.c.obj +[114/1343] Linking C static library esp-idf/esp_driver_ledc/libesp_driver_ledc.a +[115/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/mesh_event.c.obj +[116/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default_ap.c.obj +[117/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig.c.obj +[118/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_init.c.obj +[119/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_netif.c.obj +[120/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_common.c.obj +[121/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/regulatory/esp_wifi_regulatory.c.obj +[122/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug_diagram.c.obj +[123/1343] Building C object esp-idf/esp_driver_pcnt/CMakeFiles/__idf_esp_driver_pcnt.dir/src/pulse_cnt.c.obj +[124/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/wifi_default.c.obj +[125/1343] Linking C static library esp-idf/esp_driver_i2c/libesp_driver_i2c.a +[126/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave.c.obj +[127/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/src/coexist_debug.c.obj +[128/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_slave_hd.c.obj +[129/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/esp32s3/esp_adapter.c.obj +[130/1343] Building C object esp-idf/esp_wifi/CMakeFiles/__idf_esp_wifi.dir/src/smartconfig_ack.c.obj +[131/1343] Linking C static library esp-idf/esp_driver_sdm/libesp_driver_sdm.a +[132/1343] Building C object esp-idf/esp_coex/CMakeFiles/__idf_esp_coex.dir/esp32s3/esp_coex_adapter.c.obj +[133/1343] Building C object esp-idf/esp_driver_spi/CMakeFiles/__idf_esp_driver_spi.dir/src/gpspi/spi_master.c.obj +[134/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/os_xtensa.c.obj +[135/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ap_config.c.obj +[136/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/pmksa_cache_auth.c.obj +[137/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_1x.c.obj +[138/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth_ie.c.obj +[139/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/comeback_token.c.obj +[140/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/sta_info.c.obj +[141/1343] Linking C static library esp-idf/esp_driver_tsens/libesp_driver_tsens.a +[142/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/dragonfly.c.obj +[143/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/port/eloop.c.obj +[144/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/ieee802_11.c.obj +[145/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/bitfield.c.obj +[146/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/wpa_common.c.obj +[147/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-siv.c.obj +[148/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-kdf.c.obj +[149/1343] Linking C static library esp-idf/esp_driver_rmt/libesp_driver_rmt.a +[150/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_ops.c.obj +[151/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/ap/wpa_auth.c.obj +[152/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ccmp.c.obj +[153/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_group5.c.obj +[154/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-gcm.c.obj +[155/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/dh_groups.c.obj +[156/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-tlsprf.c.obj +[157/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/ms_funcs.c.obj +[158/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tlsprf.c.obj +[159/1343] Linking C static library esp-idf/esp_driver_sdspi/libesp_driver_sdspi.a +[160/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-tlsprf.c.obj +[161/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae.c.obj +[162/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha384-prf.c.obj +[163/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha256-prf.c.obj +[164/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-prf.c.obj +[165/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/md4-internal.c.obj +[166/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_common/eap_wsc_common.c.obj +[167/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/sha1-tprf.c.obj +[168/1343] Linking C static library esp-idf/esp_driver_sdmmc/libesp_driver_sdmmc.a +[169/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/chap.c.obj +[170/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/ieee802_11_common.c.obj +[171/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_common.c.obj +[172/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap_common.c.obj +[173/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls.c.obj +[174/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/mschapv2.c.obj +[175/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap.c.obj +[176/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_mschapv2.c.obj +[177/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_tls_common.c.obj +[178/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_common.c.obj +[179/1343] Linking C static library esp-idf/sdmmc/libsdmmc.a +[180/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_peap.c.obj +[181/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/pmksa_cache.c.obj +[182/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_ttls.c.obj +[183/1343] Linking C static library esp-idf/esp_driver_i2s/libesp_driver_i2s.a +[184/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/uuid.c.obj +[185/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/base64.c.obj +[186/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpa_debug.c.obj +[187/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast_pac.c.obj +[188/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/ext_password.c.obj +[189/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa_ie.c.obj +[190/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/wpabuf.c.obj +[191/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/eap_peer/eap_fast.c.obj +[192/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/json.c.obj +[193/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/utils/common.c.obj +[194/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps.c.obj +[195/1343] Linking C static library esp-idf/esp_driver_mcpwm/libesp_driver_mcpwm.a +[196/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa2_api_port.c.obj +[197/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_build.c.obj +[198/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_process.c.obj +[199/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_attr_parse.c.obj +[200/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/rsn_supp/wpa.c.obj +[201/1343] Linking C static library esp-idf/esp_driver_pcnt/libesp_driver_pcnt.a +[202/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_common.c.obj +[203/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_dev_attr.c.obj +[204/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/common/sae_pk.c.obj +[205/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpas_glue.c.obj +[206/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa_main.c.obj +[207/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_common.c.obj +[208/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_owe.c.obj +[209/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/wps/wps_enrollee.c.obj +[210/1343] Linking C static library esp-idf/esp_gdbstub/libesp_gdbstub.a +[211/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wpa3.c.obj +[212/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpsk.c.obj +[213/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_eap_client.c.obj +[214/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_hostap.c.obj +[215/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls.c.obj +[216/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/esp_wps.c.obj +[217/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/tls_mbedtls.c.obj +[218/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/rc4.c.obj +[219/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c.obj +[220/1343] Linking C static library esp-idf/esp_driver_spi/libesp_driver_spi.a +[221/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/fastpbkdf2.c.obj +[222/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_defaults.c.obj +[223/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-wrap.c.obj +[224/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/des-internal.c.obj +[225/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-unwrap.c.obj +[226/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_objects.c.obj +[227/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c.obj +[228/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/esp_netif_handlers.c.obj +[229/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/aes-ccm.c.obj +[230/1343] Linking C static library esp-idf/esp_wifi/libesp_wifi.a +[231/1343] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/esp_supplicant/src/crypto/crypto_mbedtls-ec.c.obj +[232/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_sntp.c.obj +[233/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip_defaults.c.obj +[234/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/wlanif.c.obj +[235/1343] Linking C static library esp-idf/esp_coex/libesp_coex.a +[236/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/ethernetif.c.obj +[237/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/netif/esp_pbuf_ref.c.obj +[238/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/err.c.obj +[239/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/sntp/sntp.c.obj +[240/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netbuf.c.obj +[241/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/if_api.c.obj +[242/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netifapi.c.obj +[243/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_lib.c.obj +[244/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/netdb.c.obj +[245/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/tcpip.c.obj +[246/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/api_msg.c.obj +[247/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/def.c.obj +[248/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/sntp/sntp.c.obj +[249/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/mem.c.obj +[250/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/init.c.obj +[251/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ip.c.obj +[252/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/memp.c.obj +[253/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/apps/netbiosns/netbiosns.c.obj +[254/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/inet_chksum.c.obj +[255/1343] Building C object esp-idf/esp_netif/CMakeFiles/__idf_esp_netif.dir/lwip/esp_netif_lwip.c.obj +[256/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/dns.c.obj +[257/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/pbuf.c.obj +[258/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/netif.c.obj +[259/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/sys.c.obj +[260/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/raw.c.obj +[261/1343] Linking C static library esp-idf/wpa_supplicant/libwpa_supplicant.a +[262/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/stats.c.obj +[263/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/autoip.c.obj +[264/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/timeouts.c.obj +[265/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/api/sockets.c.obj +[266/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/udp.c.obj +[267/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/dhcp6.c.obj +[268/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/etharp.c.obj +[269/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/icmp.c.obj +[270/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_out.c.obj +[271/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_frag.c.obj +[272/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4.c.obj +[273/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_addr.c.obj +[274/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ethip6.c.obj +[275/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp_in.c.obj +[276/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/igmp.c.obj +[277/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/tcp.c.obj +[278/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/ip4_napt.c.obj +[279/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/icmp6.c.obj +[280/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/dhcp.c.obj +[281/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/inet6.c.obj +[282/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_addr.c.obj +[283/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6_frag.c.obj +[284/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ethernet.c.obj +[285/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif.c.obj +[286/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/mld6.c.obj +[287/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ccp.c.obj +[288/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/auth.c.obj +[289/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/bridgeif_fdb.c.obj +[290/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap_ms.c.obj +[291/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-new.c.obj +[292/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/chap-md5.c.obj +[293/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/demand.c.obj +[294/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/slipif.c.obj +[295/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eap.c.obj +[296/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/ip6.c.obj +[297/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ecp.c.obj +[298/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/eui64.c.obj +[299/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/fsm.c.obj +[300/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipcp.c.obj +[301/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/lcp.c.obj +[302/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/magic.c.obj +[303/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ipv6cp.c.obj +[304/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/multilink.c.obj +[305/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/mppe.c.obj +[306/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/ppp.c.obj +[307/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppapi.c.obj +[308/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppcrypt.c.obj +[309/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv6/nd6.c.obj +[310/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppoe.c.obj +[311/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppol2tp.c.obj +[312/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/pppos.c.obj +[313/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/upap.c.obj +[314/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/utils.c.obj +[315/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/vj.c.obj +[316/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/tcp_isn_default.c.obj +[317/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/hooks/lwip_default_hooks.c.obj +[318/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/if_index.c.obj +[319/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/sockets_ext.c.obj +[320/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/debug/lwip_debug.c.obj +[321/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/esp_ping.c.obj +[322/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/esp32xx/vfs_lwip.c.obj +[323/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/des.c.obj +[324/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md5.c.obj +[325/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/acd_dhcp_check.c.obj +[326/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/port/freertos/sys_arch.c.obj +[327/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping.c.obj +[328/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/md4.c.obj +[329/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/sha1.c.obj +[330/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/netif/ppp/polarssl/arc4.c.obj +[331/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/ping/ping_sock.c.obj +[332/1343] Linking C static library esp-idf/esp_netif/libesp_netif.a +[333/1343] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/apps/dhcpserver/dhcpserver.c.obj +[334/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/esp32s3/phy_init_data.c.obj +[335/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/lib_printf.c.obj +[336/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_common.c.obj +[337/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_connection_monitor.c.obj +[338/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/btbb_init.c.obj +[339/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_override.c.obj +[340/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag.c.obj +[341/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_eventfd.c.obj +[342/1343] Building C object esp-idf/esp_vfs_console/CMakeFiles/__idf_esp_vfs_console.dir/vfs_console.c.obj +[343/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/nullfs.c.obj +[344/1343] Building C object esp-idf/esp_phy/CMakeFiles/__idf_esp_phy.dir/src/phy_init.c.obj +[345/1343] Building C object esp-idf/esp_driver_usb_serial_jtag/CMakeFiles/__idf_esp_driver_usb_serial_jtag.dir/src/usb_serial_jtag_vfs.c.obj +[346/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs_semihost.c.obj +[347/1343] Building C object esp-idf/vfs/CMakeFiles/__idf_vfs.dir/vfs.c.obj +[348/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_platform.cpp.obj +[349/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader.c.obj +[350/1343] Linking C static library esp-idf/lwip/liblwip.a +[351/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_aes.c.obj +[352/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition.cpp.obj +[353/1343] Linking C static library esp-idf/vfs/libvfs.a +[354/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_lookup.cpp.obj +[355/1343] Building C object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_bootloader_xts_aes.c.obj +[356/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/default_event_loop.c.obj +[357/1343] Linking C static library esp-idf/esp_vfs_console/libesp_vfs_console.a +[358/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event_private.c.obj +[359/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_wakeup.c.obj +[360/1343] Linking C static library esp-idf/esp_driver_usb_serial_jtag/libesp_driver_usb_serial_jtag.a +[361/1343] Building C object esp-idf/esp_event/CMakeFiles/__idf_esp_event.dir/esp_event.c.obj +[362/1343] Linking C static library esp-idf/esp_phy/libesp_phy.a +[363/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uhci.c.obj +[364/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart_vfs.c.obj +[365/1343] Building C object esp-idf/esp_ringbuf/CMakeFiles/__idf_esp_ringbuf.dir/ringbuf.c.obj +[366/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer_common.c.obj +[367/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_init.c.obj +[368/1343] Building C object esp-idf/esp_driver_gptimer/CMakeFiles/__idf_esp_driver_gptimer.dir/src/gptimer.c.obj +[369/1343] Building C object esp-idf/esp_driver_uart/CMakeFiles/__idf_esp_driver_uart.dir/src/uart.c.obj +[370/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer.c.obj +[371/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/system_time.c.obj +[372/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/ets_timer_legacy.c.obj +[373/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_common.c.obj +[374/1343] Building C object esp-idf/esp_timer/CMakeFiles/__idf_esp_timer.dir/src/esp_timer_impl_systimer.c.obj +[375/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_exception_stubs.cpp.obj +[376/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_init.cpp.obj +[377/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread.c.obj +[378/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_cond_var.c.obj +[379/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_local_storage.c.obj +[380/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_rwlock.c.obj +[381/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/init.c.obj +[382/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/abort.c.obj +[383/1343] Building C object esp-idf/pthread/CMakeFiles/__idf_pthread.dir/pthread_semaphore.c.obj +[384/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/assert.c.obj +[385/1343] Building CXX object esp-idf/cxx/CMakeFiles/__idf_cxx.dir/cxx_guards.cpp.obj +[386/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/heap.c.obj +[387/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/poll.c.obj +[388/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_locked.cpp.obj +[389/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_item_hash_list.cpp.obj +[390/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/locks.c.obj +[391/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/random.c.obj +[392/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/pthread.c.obj +[393/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_cxx_api.cpp.obj +[394/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_encrypted_partition.cpp.obj +[395/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/getentropy.c.obj +[396/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/termios.c.obj +[397/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_pagemanager.cpp.obj +[398/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_partition_manager.cpp.obj +[399/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_handle_simple.cpp.obj +[400/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/sysconf.c.obj +[401/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/scandir.c.obj +[402/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/realpath.c.obj +[403/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/syscalls.c.obj +[404/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/flockfile.c.obj +[405/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_types.cpp.obj +[406/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_init.c.obj +[407/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/esp_time_impl.c.obj +[408/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/time.c.obj +[409/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_page.cpp.obj +[410/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/newlib_init.c.obj +[411/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/reent_syscalls.c.obj +[412/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_storage.cpp.obj +[413/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/heap_idf.c.obj +[414/1343] Building CXX object esp-idf/nvs_flash/CMakeFiles/__idf_nvs_flash.dir/src/nvs_api.cpp.obj +[415/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/port/xtensa/stdatomic_s32c1i.c.obj +[416/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/list.c.obj +[417/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/app_startup.c.obj +[418/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_common.c.obj +[419/1343] Building ASM object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/portasm.S.obj +[420/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_init.c.obj +[421/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/port_systick.c.obj +[422/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/event_groups.c.obj +[423/1343] Building C object esp-idf/newlib/CMakeFiles/__idf_newlib.dir/src/stdatomic.c.obj +[424/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/xtensa_overlay_os_hook.c.obj +[425/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/timers.c.obj +[426/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/stream_buffer.c.obj +[427/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/queue.c.obj +[428/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/freertos_compatibility.c.obj +[429/1343] Linking C static library esp-idf/nvs_flash/libnvs_flash.a +[430/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/cpu_region_protect.c.obj +[431/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/portable/xtensa/port.c.obj +[432/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions_event_groups.c.obj +[433/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_cpu_intr.c.obj +[434/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_memory_utils.c.obj +[435/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/cpu.c.obj +[436/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/esp_additions/idf_additions.c.obj +[437/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/hw_random.c.obj +[438/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/revision.c.obj +[439/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_gpio_reserve.c.obj +[440/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_ctrl_os.c.obj +[441/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clk.c.obj +[442/1343] Linking C static library esp-idf/esp_event/libesp_event.a +[443/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mac_addr.c.obj +[444/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/regi2c_ctrl.c.obj +[445/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_clk_tree.c.obj +[446/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/io_mux.c.obj +[447/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/periph_ctrl.c.obj +[448/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/rtc_module.c.obj +[449/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sar_periph_ctrl_common.c.obj +[450/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/intr_alloc.c.obj +[451/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_dma_utils.c.obj +[452/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/clk_utils.c.obj +[453/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_clk_tree_common.c.obj +[454/1343] Linking C static library esp-idf/esp_driver_uart/libesp_driver_uart.a +[455/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_mspi.c.obj +[456/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma_link.c.obj +[457/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_usb.c.obj +[458/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_share_hw_ctrl.c.obj +[459/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/spi_bus_lock.c.obj +[460/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modem.c.obj +[461/1343] Building C object esp-idf/freertos/CMakeFiles/__idf_freertos.dir/FreeRTOS-Kernel/tasks.c.obj +[462/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_console.c.obj +[463/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/adc_share_hw_ctrl.c.obj +[464/1343] Linking C static library esp-idf/esp_ringbuf/libesp_ringbuf.a +[465/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/esp_async_memcpy.c.obj +[466/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/systimer.c.obj +[467/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_event.c.obj +[468/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_gpio.c.obj +[469/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/deprecated/gdma_legacy.c.obj +[470/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/mspi_timing_tuning.c.obj +[471/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_wake_stub.c.obj +[472/1343] Linking C static library esp-idf/esp_driver_gptimer/libesp_driver_gptimer.a +[473/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk_init.c.obj +[474/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/esp_clock_output.c.obj +[475/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/chip_info.c.obj +[476/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/async_memcpy_gdma.c.obj +[477/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/power_supply/brownout.c.obj +[478/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_sleep.c.obj +[479/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp_memprot_conv.c.obj +[480/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_time.c.obj +[481/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/sar_periph_ctrl.c.obj +[482/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_init.c.obj +[483/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/dma/gdma.c.obj +[484/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_config.c.obj +[485/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/rtc_clk.c.obj +[486/1343] Linking C static library esp-idf/esp_timer/libesp_timer.a +[487/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_lock.c.obj +[488/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/sleep_modes.c.obj +[489/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/dport_access_common.c.obj +[490/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/init.c.obj +[491/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/lldesc.c.obj +[492/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/interrupts.c.obj +[493/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gpio_periph.c.obj +[494/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/adc_periph.c.obj +[495/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_hmac.c.obj +[496/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_crypto_periph_clk.c.obj +[497/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/uart_periph.c.obj +[498/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/dedic_gpio_periph.c.obj +[499/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/mspi_timing_tuning/port/esp32s3/mspi_timing_by_mspi_delay.c.obj +[500/1343] Building C object esp-idf/esp_security/CMakeFiles/__idf_esp_security.dir/src/esp_ds.c.obj +[501/1343] Linking C static library esp-idf/cxx/libcxx.a +[502/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/gdma_periph.c.obj +[503/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/lowpower/port/esp32s3/sleep_cpu.c.obj +[504/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/spi_periph.c.obj +[505/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdm_periph.c.obj +[506/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/ledc_periph.c.obj +[507/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rmt_periph.c.obj +[508/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/pcnt_periph.c.obj +[509/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2s_periph.c.obj +[510/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/lcd_periph.c.obj +[511/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/timer_periph.c.obj +[512/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/temperature_sensor_periph.c.obj +[513/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/touch_sensor_periph.c.obj +[514/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/i2c_periph.c.obj +[515/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mcpwm_periph.c.obj +[516/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/twai_periph.c.obj +[517/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/mpi_periph.c.obj +[518/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/usb_dwc_periph.c.obj +[519/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/wdt_periph.c.obj +[520/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/sdmmc_periph.c.obj +[521/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/cam_periph.c.obj +[522/1343] Linking C static library esp-idf/pthread/libpthread.a +[523/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/power_supply_periph.c.obj +[524/1343] Building C object esp-idf/soc/CMakeFiles/__idf_soc.dir/esp32s3/rtc_io_periph.c.obj +[525/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/util.c.obj +[526/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/esp32s3/memory_layout.c.obj +[527/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/port/memory_layout_utils.c.obj +[528/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_base.c.obj +[529/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_format_text.c.obj +[530/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/util.c.obj +[531/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/buffer/log_buffers.c.obj +[532/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_lock.c.obj +[533/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_timestamp_common.c.obj +[534/1343] Building C object esp-idf/esp_hw_support/CMakeFiles/__idf_esp_hw_support.dir/port/esp32s3/esp_memprot.c.obj +[535/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_timestamp.c.obj +[536/1343] Linking C static library esp-idf/newlib/libnewlib.a +[537/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps_init.c.obj +[538/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/multi_heap.c.obj +[539/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_print.c.obj +[540/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/tag_log_level.c.obj +[541/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/os/log_write.c.obj +[542/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/log_level.c.obj +[543/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log.c.obj +[544/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/heap_caps.c.obj +[545/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/linked_list/log_linked_list.c.obj +[546/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hal_utils.c.obj +[547/1343] Building C object esp-idf/log/CMakeFiles/__idf_log.dir/src/log_level/tag_log_level/cache/log_binary_heap.c.obj +[548/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpu_hal.c.obj +[549/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/efuse_hal.c.obj +[550/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/efuse_hal.c.obj +[551/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/color_hal.c.obj +[552/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mmu_hal.c.obj +[553/1343] Linking C static library esp-idf/freertos/libfreertos.a +[554/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_encrypt_hal_iram.c.obj +[555/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gpio_hal.c.obj +[556/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal_iram.c.obj +[557/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cache_hal.c.obj +[558/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/timer_hal.c.obj +[559/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal.c.obj +[560/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rtc_io_hal.c.obj +[561/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/clk_tree_hal.c.obj +[562/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/systimer_hal.c.obj +[563/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uart_hal.c.obj +[564/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal.c.obj +[565/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ledc_hal_iram.c.obj +[566/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_iram.c.obj +[567/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal.c.obj +[568/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/pcnt_hal.c.obj +[569/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/rmt_hal.c.obj +[570/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2c_hal_iram.c.obj +[571/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/uhci_hal.c.obj +[572/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdm_hal.c.obj +[573/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_top.c.obj +[574/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mcpwm_hal.c.obj +[575/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sdmmc_hal.c.obj +[576/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/gdma_hal_ahb_v1.c.obj +[577/1343] Building C object esp-idf/heap/CMakeFiles/__idf_heap.dir/tlsf/tlsf.c.obj +[578/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal_common.c.obj +[579/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/twai_hal_v1.c.obj +[580/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/lcd_hal.c.obj +[581/1343] Linking C static library esp-idf/esp_hw_support/libesp_hw_support.a +[582/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/i2s_hal.c.obj +[583/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_oneshot_hal.c.obj +[584/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/sha_hal.c.obj +[585/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/mpi_hal.c.obj +[586/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/adc_hal.c.obj +[587/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/aes_hal.c.obj +[588/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/brownout_hal.c.obj +[589/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal.c.obj +[590/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal.c.obj +[591/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hal_iram.c.obj +[592/1343] Linking C static library esp-idf/esp_security/libesp_security.a +[593/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_slave_hd_hal.c.obj +[594/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_hal_iram.c.obj +[595/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/ds_hal.c.obj +[596/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_serial_jtag_hal.c.obj +[597/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/hmac_hal.c.obj +[598/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_wrap_hal.c.obj +[599/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/spi_flash_hal_gpspi.c.obj +[600/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/cam_hal.c.obj +[601/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sens_hal.c.obj +[602/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/touch_sensor_hal.c.obj +[603/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/xt_wdt_hal.c.obj +[604/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_sys.c.obj +[605/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/touch_sensor_hal.c.obj +[606/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_crc.c.obj +[607/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/esp32s3/rtc_cntl_hal.c.obj +[608/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_efuse.c.obj +[609/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_longjmp.S.obj +[610/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_gpio.c.obj +[611/1343] Building C object esp-idf/hal/CMakeFiles/__idf_hal.dir/usb_dwc_hal.c.obj +[612/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_spiflash.c.obj +[613/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_uart.c.obj +[614/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_systimer.c.obj +[615/1343] Building ASM object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_writeback_esp32s3.S.obj +[616/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_print.c.obj +[617/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_cache_esp32s2_esp32s3.c.obj +[618/1343] Building C object esp-idf/esp_rom/CMakeFiles/__idf_esp_rom.dir/patches/esp_rom_wdt.c.obj +[619/1343] Linking C static library esp-idf/soc/libsoc.a +[620/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_err.c.obj +[621/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/crosscore_int.c.obj +[622/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system_console.c.obj +[623/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_ipc.c.obj +[624/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/stack_check.c.obj +[625/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/esp_system.c.obj +[626/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup.c.obj +[627/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/freertos_hooks.c.obj +[628/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/system_time.c.obj +[629/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/ubsan.c.obj +[630/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/int_wdt.c.obj +[631/1343] Linking C static library esp-idf/heap/libheap.a +[632/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/panic.c.obj +[633/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/xt_wdt.c.obj +[634/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_routines.S.obj +[635/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/startup_funcs.c.obj +[636/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_handler.S.obj +[637/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/esp_ipc_isr_port.c.obj +[638/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/panic_handler.c.obj +[639/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_handler_asm.S.obj +[640/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_system_chip.c.obj +[641/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/image_process.c.obj +[642/1343] Building C object esp-idf/esp_common/CMakeFiles/__idf_esp_common.dir/src/esp_err_to_name.c.obj +[643/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack_asm.S.obj +[644/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/esp_ipc_isr.c.obj +[645/1343] Linking C static library esp-idf/log/liblog.a +[646/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers_asm.S.obj +[647/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt.c.obj +[648/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/panic_arch.c.obj +[649/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/task_wdt/task_wdt_impl_timergroup.c.obj +[650/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/expression_with_stack.c.obj +[651/1343] Building ASM object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/highint_hdl.S.obj +[652/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_stubs.c.obj +[653/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/cpu_start.c.obj +[654/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/debug_helpers.c.obj +[655/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/arch/xtensa/trax.c.obj +[656/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_brownout_hook.c.obj +[657/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/reset_reason.c.obj +[658/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_drivers.c.obj +[659/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/apb_backup_dma.c.obj +[660/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_hpm_enable.c.obj +[661/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/cache_err_int.c.obj +[662/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/system_internal.c.obj +[663/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp32s3/spi_flash_oct_flash_init.c.obj +[664/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_issi.c.obj +[665/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_boya.c.obj +[666/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic.c.obj +[667/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_th.c.obj +[668/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_gd.c.obj +[669/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_winbond.c.obj +[670/1343] Building C object esp-idf/esp_system/CMakeFiles/__idf_esp_system.dir/port/soc/esp32s3/clk.c.obj +[671/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_mxic_opi.c.obj +[672/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/memspi_host_driver.c.obj +[673/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_chip_generic.c.obj +[674/1343] Linking C static library esp-idf/hal/libhal.a +[675/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_wrap.c.obj +[676/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_noos.c.obj +[677/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/port/esp32s3/ext_mem_layout.c.obj +[678/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_mmap.c.obj +[679/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/heap_align_hw.c.obj +[680/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/cache_utils.c.obj +[681/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/flash_ops.c.obj +[682/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_utils.c.obj +[683/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/spi_flash_os_func_app.c.obj +[684/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_cache_msync.c.obj +[685/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common_loader.c.obj +[686/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_mem.c.obj +[687/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_common.c.obj +[688/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_spi_init.c.obj +[689/1343] Linking C static library esp-idf/esp_rom/libesp_rom.a +[690/1343] Building C object esp-idf/esp_mm/CMakeFiles/__idf_esp_mm.dir/esp_mmu_map.c.obj +[691/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_clock_init.c.obj +[692/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_efuse.c.obj +[693/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random.c.obj +[694/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_random_esp32s3.c.obj +[695/1343] Building C object esp-idf/spi_flash/CMakeFiles/__idf_spi_flash.dir/esp_flash_api.c.obj +[696/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_encrypt.c.obj +[697/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/secure_boot.c.obj +[698/1343] Linking C static library esp-idf/esp_common/libesp_common.a +[699/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/flash_partitions.c.obj +[700/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/flash_qio_mode.c.obj +[701/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash.c.obj +[702/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp32s3/secure_boot_secure_features.c.obj +[703/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_fields.c.obj +[704/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_sha.c.obj +[705/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_table.c.obj +[706/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/bootloader_flash/src/bootloader_flash_config_esp32s3.c.obj +[707/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_rtc_calib.c.obj +[708/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_fields.c.obj +[709/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/esp32s3/esp_efuse_utility.c.obj +[710/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_api.c.obj +[711/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/esp_image_format.c.obj +[712/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_utility.c.obj +[713/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/esp_efuse_startup.c.obj +[714/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_app_desc.c.obj +[715/1343] Building C object esp-idf/efuse/CMakeFiles/__idf_efuse.dir/src/efuse_controller/keys/with_key_purposes/esp_efuse_api_key.c.obj +[716/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/debug.c.obj +[717/1343] Building C object esp-idf/esp_bootloader_format/CMakeFiles/__idf_esp_bootloader_format.dir/esp_bootloader_desc.c.obj +[718/1343] Building C object esp-idf/bootloader_support/CMakeFiles/__idf_bootloader_support.dir/src/bootloader_utility.c.obj +[719/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition_target.c.obj +[720/1343] Building C object esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj +[721/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_reader.c.obj +[722/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/mps_trace.c.obj +[723/1343] Building C object esp-idf/esp_partition/CMakeFiles/__idf_esp_partition.dir/partition.c.obj +[724/1343] Linking C static library esp-idf/esp_system/libesp_system.a +[725/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_keys.c.obj +[726/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cache.c.obj +[727/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_client.c.obj +[728/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_generic.c.obj +[729/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls13_server.c.obj +[730/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ciphersuites.c.obj +[731/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_cookie.c.obj +[732/1343] Building C object esp-idf/app_update/CMakeFiles/__idf_app_update.dir/esp_ota_ops.c.obj +[733/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_debug_helpers_generated.c.obj +[734/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_ticket.c.obj +[735/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_client.c.obj +[736/1343] Linking C static library esp-idf/spi_flash/libspi_flash.a +[737/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_platform_time.c.obj +[738/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/mbedtls_debug.c.obj +[739/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_create.c.obj +[740/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_msg.c.obj +[741/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_client.c.obj +[742/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls12_server.c.obj +[743/1343] Linking C static library esp-idf/esp_mm/libesp_mm.a +[744/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_csr.c.obj +[745/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/pkcs7.c.obj +[746/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crl.c.obj +[747/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write.c.obj +[748/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/net_sockets.c.obj +[749/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_csr.c.obj +[750/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509write_crt.c.obj +[751/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesni.c.obj +[752/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aes.c.obj +[753/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aesce.c.obj +[754/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509.c.obj +[755/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod.c.obj +[756/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1parse.c.obj +[757/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_mod_raw.c.obj +[758/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/camellia.c.obj +[759/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/base64.c.obj +[760/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/asn1write.c.obj +[761/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/block_cipher.c.obj +[762/1343] Linking C static library esp-idf/bootloader_support/libbootloader_support.a +[763/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chacha20.c.obj +[764/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/aria.c.obj +[765/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chachapoly.c.obj +[766/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedtls.dir/ssl_tls.c.obj +[767/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum_core.c.obj +[768/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ccm.c.obj +[769/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedx509.dir/x509_crt.c.obj +[770/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/des.c.obj +[771/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/dhm.c.obj +[772/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/constant_time.c.obj +[773/1343] Linking C static library esp-idf/efuse/libefuse.a +[774/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecjpake.c.obj +[775/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdh.c.obj +[776/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher_wrap.c.obj +[777/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher.c.obj +[778/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/bignum.c.obj +[779/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cmac.c.obj +[780/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves_new.c.obj +[781/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ctr_drbg.c.obj +[782/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecdsa.c.obj +[783/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy_poll.c.obj +[784/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hkdf.c.obj +[785/1343] Linking C static library esp-idf/esp_partition/libesp_partition.a +[786/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/entropy.c.obj +[787/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/memory_buffer_alloc.c.obj +[788/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/nist_kw.c.obj +[789/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/error.c.obj +[790/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp_curves.c.obj +[791/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lmots.c.obj +[792/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md5.c.obj +[793/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/padlock.c.obj +[794/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/gcm.c.obj +[795/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/hmac_drbg.c.obj +[796/1343] Linking C static library esp-idf/app_update/libapp_update.a +[797/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/lms.c.obj +[798/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ecp.c.obj +[799/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/md.c.obj +[800/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_ecc.c.obj +[801/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pem.c.obj +[802/1343] Linking C static library esp-idf/esp_bootloader_format/libesp_bootloader_format.a +[803/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/oid.c.obj +[804/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/poly1305.c.obj +[805/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform.c.obj +[806/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs5.c.obj +[807/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkcs12.c.obj +[808/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/platform_util.c.obj +[809/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk_wrap.c.obj +[810/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pk.c.obj +[811/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkwrite.c.obj +[812/1343] Linking C static library esp-idf/esp_app_format/libesp_app_format.a +[813/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_aead.c.obj +[814/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_client.c.obj +[815/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/pkparse.c.obj +[816/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_cipher.c.obj +[817/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_driver_wrappers_no_static.c.obj +[818/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ffdh.c.obj +[819/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_se.c.obj +[820/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_pake.c.obj +[821/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_ecp.c.obj +[822/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_hash.c.obj +[823/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_mac.c.obj +[824/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_rsa.c.obj +[825/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ripemd160.c.obj +[826/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_its_file.c.obj +[827/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedtls.a +[828/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_storage.c.obj +[829/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_util.c.obj +[830/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto_slot_management.c.obj +[831/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha256.c.obj +[832/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha3.c.obj +[833/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa_alt_helpers.c.obj +[834/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/threading.c.obj +[835/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha1.c.obj +[836/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/timing.c.obj +[837/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/sha512.c.obj +[838/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version.c.obj +[839/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/version_features.c.obj +[840/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha_gdma_impl.c.obj +[841/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_gdma_impl.c.obj +[842/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_mem.c.obj +[843/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hardware.c.obj +[844/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_timing.c.obj +[845/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_xts.c.obj +[846/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_common.c.obj +[847/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c.obj +[848/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes_dma_core.c.obj +[849/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/esp_sha.c.obj +[850/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c.obj +[851/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_hmac_pbkdf2.c.obj +[852/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/bignum_alt.c.obj +[853/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/sha.c.obj +[854/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_dec_alt.c.obj +[855/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/rsa.c.obj +[856/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c.obj +[857/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/esp_ds/esp_ds_common.c.obj +[858/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/bignum/esp_bignum.c.obj +[859/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha256.c.obj +[860/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha1.c.obj +[861/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/md/esp_md.c.obj +[862/1343] Creating directories for 'bootloader' +[863/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedx509.a +[864/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/sha/core/esp_sha512.c.obj +[865/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m/p256-m.c.obj +[866/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/everest.c.obj +[867/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/x25519.c.obj +[868/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/p256-m/CMakeFiles/p256m.dir/p256-m_driver_entrypoints.c.obj +[869/1343] Building C object esp-idf/mbedtls/mbedtls/3rdparty/everest/CMakeFiles/everest.dir/library/Hacl_Curve25519_joined.c.obj +[870/1343] No download step for 'bootloader' +[871/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/Users/massif/esp/v5.5.2/esp-idf/components/mbedtls/port/aes/esp_aes_gcm.c.obj +[872/1343] No update step for 'bootloader' +[873/1343] No patch step for 'bootloader' +[874/1343] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/psa_crypto.c.obj +[875/1343] Minifying + gzipping web resources +Minifying web resources in /tmp/tianshan-xterm-build/build/esp-idf/ts_webui/web_optimized... + JS js/terminal.js: 31,120 -> 20,078 (35.5% saved) + JS js/router.js: 6,414 -> 3,839 (40.1% saved) + JS js/dragSort.js: 11,460 -> 7,603 (33.7% saved) + JS js/api.js: 36,638 -> 24,339 (33.6% saved) + JS js/i18n.js: 7,208 -> 4,320 (40.1% saved) + JS js/app.js: 1,129,944 -> 840,829 (25.6% saved) + JS js/lang/en-US.js: 178,439 -> 143,161 (19.8% saved) + JS js/lang/zh-CN.js: 172,046 -> 137,314 (20.2% saved) + CSS css/style.css: 179,071 -> 129,275 (27.8% saved) + CSS fonts/remixicon.css: 5,940 -> 4,860 (18.2% saved) + + Total saved: 442,662 bytes (432.3 KB) + +Gzipping web resources in /tmp/tianshan-xterm-build/build/esp-idf/ts_webui/web_optimized... + GZ js/terminal.js: 20,078 -> 5,569 (72.3% smaller) + GZ js/router.js: 3,839 -> 1,340 (65.1% smaller) + GZ js/dragSort.js: 7,603 -> 1,869 (75.4% smaller) + GZ js/api.js: 24,339 -> 6,163 (74.7% smaller) + GZ js/i18n.js: 4,320 -> 1,460 (66.2% smaller) + GZ js/app.js: 840,829 -> 167,747 (80.0% smaller) + GZ js/lang/en-US.js: 143,161 -> 43,017 (70.0% smaller) + GZ js/lang/zh-CN.js: 137,314 -> 45,286 (67.0% smaller) + GZ vendor/xterm/xterm-addon-fit.min.js: 1,789 -> 834 (53.4% smaller) + GZ vendor/xterm/xterm.min.js: 283,670 -> 65,684 (76.8% smaller) + GZ css/style.css: 129,275 -> 20,658 (84.0% smaller) + GZ fonts/remixicon.css: 4,860 -> 1,263 (74.0% smaller) + GZ vendor/xterm/xterm.css: 5,383 -> 2,037 (62.2% smaller) + GZ index.html: 26,676 -> 7,261 (72.8% smaller) + + Gzipped 14 files: 1,633,136 -> 370,188 (77.3% overall) +Done. +[876/1343] cd /tmp/tianshan-xterm-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-xterm-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-xterm-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +FAILED: esp-idf/ts_webui/CMakeFiles/spiffs_www_bin /tmp/tianshan-xterm-build/build/esp-idf/ts_webui/CMakeFiles/spiffs_www_bin +cd /tmp/tianshan-xterm-build/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /tmp/tianshan-xterm-build/build/esp-idf/ts_webui/web_optimized /tmp/tianshan-xterm-build/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +Traceback (most recent call last): + File "/Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py", line 590, in + main() + File "/Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py", line 582, in main + spiffs.create_file('/' + os.path.relpath(full_path, args.base_dir).replace('\\', '/'), full_path) + File "/Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py", line 407, in create_file + raise RuntimeError("object name '%s' too long" % img_path) +RuntimeError: object name '/vendor/xterm/LICENSE-xterm-addon-fit' too long +[877/1343] Linking CXX static library esp-idf/mbedtls/mbedtls/library/libmbedcrypto.a +[878/1343] Performing configure step for 'bootloader' +-- Found Git: /opt/homebrew/bin/git (found version "2.51.0") +-- Minimal build - OFF +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- The ASM compiler identification is GNU +-- Found assembler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-gcc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /Users/massif/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20251107/xtensa-esp-elf/bin/xtensa-esp32s3-elf-g++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Building ESP-IDF components for target esp32s3 +-- ESP-TEE is currently supported only on the esp32c6;esp32h2;esp32c5 SoCs +-- Project sdkconfig file /tmp/tianshan-xterm-build/sdkconfig +-- Compiler supported targets: xtensa-esp-elf +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/soc/esp32s3/ld/esp32s3.peripherals.ld +-- Bootloader project name: "bootloader" version: 1 +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.bt_funcs.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libgcc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.wdt.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.version.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.libc.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom/esp32s3/ld/esp32s3.rom.newlib.ld +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.rom.ld +-- Components: bootloader bootloader_support efuse esp_app_format esp_bootloader_format esp_common esp_hw_support esp_rom esp_security esp_system esptool_py freertos hal log main micro-ecc newlib partition_table soc spi_flash xtensa +-- Component paths: /Users/massif/esp/v5.5.2/esp-idf/components/bootloader /Users/massif/esp/v5.5.2/esp-idf/components/bootloader_support /Users/massif/esp/v5.5.2/esp-idf/components/efuse /Users/massif/esp/v5.5.2/esp-idf/components/esp_app_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_bootloader_format /Users/massif/esp/v5.5.2/esp-idf/components/esp_common /Users/massif/esp/v5.5.2/esp-idf/components/esp_hw_support /Users/massif/esp/v5.5.2/esp-idf/components/esp_rom /Users/massif/esp/v5.5.2/esp-idf/components/esp_security /Users/massif/esp/v5.5.2/esp-idf/components/esp_system /Users/massif/esp/v5.5.2/esp-idf/components/esptool_py /Users/massif/esp/v5.5.2/esp-idf/components/freertos /Users/massif/esp/v5.5.2/esp-idf/components/hal /Users/massif/esp/v5.5.2/esp-idf/components/log /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/components/micro-ecc /Users/massif/esp/v5.5.2/esp-idf/components/newlib /Users/massif/esp/v5.5.2/esp-idf/components/partition_table /Users/massif/esp/v5.5.2/esp-idf/components/soc /Users/massif/esp/v5.5.2/esp-idf/components/spi_flash /Users/massif/esp/v5.5.2/esp-idf/components/xtensa +-- Adding linker script /Users/massif/esp/v5.5.2/esp-idf/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +-- Configuring done (2.1s) +-- Generating done (0.0s) +-- Build files have been written to: /tmp/tianshan-xterm-build/build/bootloader +ninja: build stopped: subcommand failed. +ninja failed with exit code 1, output of the command is in the /private/tmp/tianshan-xterm-build/build/log/idf_py_stderr_output_13331 and /private/tmp/tianshan-xterm-build/build/log/idf_py_stdout_output_13331 diff --git a/docs/repair/xterm-local/j1.txt b/docs/repair/xterm-local/j1.txt new file mode 100644 index 0000000..c36da18 --- /dev/null +++ b/docs/repair/xterm-local/j1.txt @@ -0,0 +1,10 @@ +✔ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (15.891666ms) +✔ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (5.348708ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 62.898625 diff --git a/docs/repair/xterm-local/node.txt b/docs/repair/xterm-local/node.txt new file mode 100644 index 0000000..91c5130 --- /dev/null +++ b/docs/repair/xterm-local/node.txt @@ -0,0 +1,53 @@ + +> test +> cd ../.. && node --test tests/prompts/static.test.cjs tests/prompts/regression.test.cjs + +✔ zh-CN: actual inline translator, cold language, missing/objects/parameters and confirmations (15.730084ms) +✔ zh-CN: REST business failure remains returned; strict operation rejects with original metadata (6.203792ms) +✔ zh-CN: timeout covers response body; result stays unknown for POST (8.026375ms) +✔ zh-CN: toast timer replacement, priority, safe multiline text (5.502125ms) +✔ zh-CN: actual mutations do not report success or close dialogs on business failures (5.626625ms) +✔ zh-CN: batch deletion all / partial / no success with business errors (4.978959ms) +✔ zh-CN: downloads propagate actual initiation failures and retain batch details (5.521042ms) +✔ zh-CN: file names are text; upload/verification/apply remain separate (5.504667ms) +✔ zh-CN: SSH actual event handler honors terminal states and diagnoses conflicts (4.7525ms) +✔ zh-CN: background command timeout is unconfirmed and never resubmitted (5.7085ms) +✔ zh-CN: terminal restoration waits for acknowledgement; timeout/failure stay distinct (5.863333ms) +✔ zh-CN: ping results are reachability only; failed probe is unknown and no pulse replay (5.307125ms) +✔ zh-CN: websocket label matches color across language changes and power warnings persist (4.848666ms) +✔ en-US: actual inline translator, cold language, missing/objects/parameters and confirmations (4.982166ms) +✔ en-US: REST business failure remains returned; strict operation rejects with original metadata (4.595125ms) +✔ en-US: timeout covers response body; result stays unknown for POST (6.167833ms) +✔ en-US: toast timer replacement, priority, safe multiline text (5.60625ms) +✔ en-US: actual mutations do not report success or close dialogs on business failures (5.592667ms) +✔ en-US: batch deletion all / partial / no success with business errors (5.326666ms) +✔ en-US: downloads propagate actual initiation failures and retain batch details (5.496708ms) +✔ en-US: file names are text; upload/verification/apply remain separate (5.433791ms) +✔ en-US: SSH actual event handler honors terminal states and diagnoses conflicts (7.831042ms) +✔ en-US: background command timeout is unconfirmed and never resubmitted (4.648625ms) +✔ en-US: terminal restoration waits for acknowledgement; timeout/failure stay distinct (4.474958ms) +✔ en-US: ping results are reachability only; failed probe is unknown and no pulse replay (4.458208ms) +✔ en-US: websocket label matches color across language changes and power warnings persist (4.239083ms) +✔ zh-CN: upload and download aggregates cover all success and all failure (4.610875ms) +✔ zh-CN: key deployment requires successful business code and distinguishes verification (5.354333ms) +✔ zh-CN: real LED/status renderers localize finite built-in identifiers (4.810584ms) +✔ en-US: upload and download aggregates cover all success and all failure (4.728291ms) +✔ en-US: key deployment requires successful business code and distinguishes verification (5.131292ms) +✔ en-US: real LED/status renderers localize finite built-in identifiers (4.838458ms) +✔ zh-CN: widget dynamic families render real labels and literal braces in names remain valid (4.638625ms) +✔ zh-CN: unknown stop result never escalates to forced termination (5.698834ms) +✔ en-US: widget dynamic families render real labels and literal braces in names remain valid (5.041667ms) +✔ en-US: unknown stop result never escalates to forced termination (4.4465ms) +✔ zh-CN: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (5.1135ms) +✔ en-US: J1 power alerts preserve local line, SSH ownership, transition guards and filtering (4.793083ms) +Checked 3066 references including conditional and finite dynamic families. +✔ actual UI literal/conditional and finite dynamic keys exist in both languages with matching contracts (5.766583ms) +✔ production i18n is the inline entry; no second translator script is loaded (0.089625ms) +ℹ tests 40 +ℹ suites 0 +ℹ pass 40 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 257.469375 diff --git a/docs/repair/xterm-local/offline-optimized.txt b/docs/repair/xterm-local/offline-optimized.txt new file mode 100644 index 0000000..a37d3d3 --- /dev/null +++ b/docs/repair/xterm-local/offline-optimized.txt @@ -0,0 +1,10 @@ +✔ en-US: cold offline real xterm and terminal lifecycle (970.099166ms) +✔ zh-CN: cold offline real xterm and terminal lifecycle (740.278917ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 1901.623958 diff --git a/docs/repair/xterm-local/offline-source.txt b/docs/repair/xterm-local/offline-source.txt new file mode 100644 index 0000000..ae89954 --- /dev/null +++ b/docs/repair/xterm-local/offline-source.txt @@ -0,0 +1,16 @@ + +> test:xterm +> cd ../.. && node --test tests/prompts/xterm-vendor.test.cjs tests/prompts/xterm-offline.test.cjs + +✔ en-US: cold offline real xterm and terminal lifecycle (1299.692708ms) +✔ zh-CN: cold offline real xterm and terminal lifecycle (699.31225ms) +✔ fixed vendor integrity, skip minify, gzip identity, local loader only (37.585084ms) +✔ production lazy loader: same-origin cold load, shared promise and retry (1.7135ms) +ℹ tests 4 +ℹ suites 0 +ℹ pass 4 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 2172.317625 diff --git a/docs/repair/xterm-local/optimized/requests-en-US.json b/docs/repair/xterm-local/optimized/requests-en-US.json new file mode 100644 index 0000000..c1b0be1 --- /dev/null +++ b/docs/repair/xterm-local/optimized/requests-en-US.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/en-US.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/xterm-local/optimized/requests-zh-CN.json b/docs/repair/xterm-local/optimized/requests-zh-CN.json new file mode 100644 index 0000000..ef547b7 --- /dev/null +++ b/docs/repair/xterm-local/optimized/requests-zh-CN.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/xterm-local/path-limit.txt b/docs/repair/xterm-local/path-limit.txt new file mode 100644 index 0000000..f4afb4b --- /dev/null +++ b/docs/repair/xterm-local/path-limit.txt @@ -0,0 +1,10 @@ +Traceback (most recent call last): + File "/Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py", line 590, in + main() + ~~~~^^ + File "/Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py", line 582, in main + spiffs.create_file('/' + os.path.relpath(full_path, args.base_dir).replace('\\', '/'), full_path) + ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py", line 407, in create_file + raise RuntimeError("object name '%s' too long" % img_path) +RuntimeError: object name '/vendor/xterm/LICENSE-xterm-addon-fit' too long diff --git a/docs/repair/xterm-local/project-assets-check.txt b/docs/repair/xterm-local/project-assets-check.txt new file mode 100644 index 0000000..4c96e4a --- /dev/null +++ b/docs/repair/xterm-local/project-assets-check.txt @@ -0,0 +1 @@ +PASS optimized syntax, gzip identity, cache key, and byte-identical SPIFFS reconstruction diff --git a/docs/repair/xterm-local/publication-gate.md b/docs/repair/xterm-local/publication-gate.md new file mode 100644 index 0000000..969ed3e --- /dev/null +++ b/docs/repair/xterm-local/publication-gate.md @@ -0,0 +1,9 @@ +# 提交前独立核对 + +结论:可以推送。最终生产 diff 只改变本地资源来源、缓存标识、vendor 文件和跳过第三方 minify;无 CMake、后端、SSH/J1 状态机或工作流改动。短路径由用户确认,发行文件 SHA256 未变化。 + +正向核对 loader 同源 URL → vendor → 原字节优化副本 → gzip → SPIFFS → www.bin → flasher_args;反向核对最终镜像与独立重建字节一致、实际优化资源在全新 Chrome context 禁止全部外部 origin 时正常初始化与输入。匹配/非匹配分支分别有 vendor skip/项目资源 minify、首次/重复加载、故障/恢复证据。 + +本次源与优化 Chrome、Node、J1、v3 跨层、固定 SDK 构建、产物/发布配置检查见 README。核对 build-inputs.json 全部生产哈希一致,当前 diff --check 通过。没有以旧 CI 或旧构建代替本轮验证。 + +SDK/网络边界是模拟,真实 ESP 挂载、HTTP、浏览器、SSH 和缓存升级待实机验收;有限 SPIFFS 剩余空间不代表未来可无限添加资源。只提交明确文件,原未跟踪 output/、tmp/、runtime-repair 文件保持排除。不合并、不发布、不操作设备。 diff --git a/docs/repair/xterm-local/release-static.txt b/docs/repair/xterm-local/release-static.txt new file mode 100644 index 0000000..e76e6ef --- /dev/null +++ b/docs/repair/xterm-local/release-static.txt @@ -0,0 +1,5 @@ +... +---------------------------------------------------------------------- +Ran 3 tests in 0.003s + +OK diff --git a/docs/repair/xterm-local/requests-en-US.json b/docs/repair/xterm-local/requests-en-US.json new file mode 100644 index 0000000..c1b0be1 --- /dev/null +++ b/docs/repair/xterm-local/requests-en-US.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/en-US.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/xterm-local/requests-zh-CN.json b/docs/repair/xterm-local/requests-zh-CN.json new file mode 100644 index 0000000..ef547b7 --- /dev/null +++ b/docs/repair/xterm-local/requests-zh-CN.json @@ -0,0 +1,71 @@ +{ + "requests": [ + { + "url": "http://fixture.local/", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/css/style.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-48.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/api.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/router.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/terminal.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/dragSort.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/app.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/js/lang/zh-CN.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/fonts/remixicon.woff2", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/api/v1/ota/version", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/images/tslogo-32.png", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.css?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/xterm.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + }, + { + "url": "http://fixture.local/vendor/xterm/fit.min.js?v=20260928-local-xterm", + "origin": "http://fixture.local" + } + ], + "errors": [], + "realXterm": true, + "externalRequests": 0 +} \ No newline at end of file diff --git a/docs/repair/xterm-local/runtime-search.txt b/docs/repair/xterm-local/runtime-search.txt new file mode 100644 index 0000000..b5eeeca --- /dev/null +++ b/docs/repair/xterm-local/runtime-search.txt @@ -0,0 +1,2 @@ +components/ts_webui/web/vendor/xterm/xterm.min.js:3: * Original file: /npm/xterm@5.3.0/lib/xterm.js +components/ts_webui/web/vendor/xterm/fit.min.js:3: * Original file: /npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js diff --git a/docs/repair/xterm-local/vendor-test.txt b/docs/repair/xterm-local/vendor-test.txt new file mode 100644 index 0000000..2008df8 --- /dev/null +++ b/docs/repair/xterm-local/vendor-test.txt @@ -0,0 +1,10 @@ +✔ fixed vendor integrity, skip minify, gzip identity, local loader only (40.058417ms) +✔ production lazy loader: same-origin cold load, shared promise and retry (1.65575ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 2 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 85.629625 diff --git a/docs/repair/xterm-local/vendor.json b/docs/repair/xterm-local/vendor.json new file mode 100644 index 0000000..c011bba --- /dev/null +++ b/docs/repair/xterm-local/vendor.json @@ -0,0 +1,52 @@ +[ + { + "package": "xterm", + "version": "5.3.0", + "original": "lib/xterm.min.js", + "file": "xterm.min.js", + "source": "https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js", + "sha256": "fc1dd31b221e3e5f929486e07a80b477a8aaf9dce2b4f9c3ffe7dd25f370655d", + "bytes": 283670, + "license": "MIT" + }, + { + "package": "xterm", + "version": "5.3.0", + "original": "css/xterm.css", + "file": "xterm.css", + "source": "https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css", + "sha256": "832f3f2c603b43ad4351ff04970150cc7a873014276db126a6065c6dd81e4872", + "bytes": 5383, + "license": "MIT" + }, + { + "package": "xterm-addon-fit", + "version": "0.8.0", + "original": "lib/xterm-addon-fit.min.js", + "file": "fit.min.js", + "source": "https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js", + "sha256": "c78e5795c6487acdf24ab436798d4a9cec3848101b281bc65b061f39db714be1", + "bytes": 1789, + "license": "MIT" + }, + { + "package": "xterm", + "version": "5.3.0", + "original": "LICENSE", + "file": "LICENSE-xterm", + "source": "https://cdn.jsdelivr.net/npm/xterm@5.3.0/LICENSE", + "sha256": "b569f629d00f2626a8100df2a1798210535621e42164dfd426a6fe5aac7b0ccd", + "bytes": 1261, + "license": "MIT" + }, + { + "package": "xterm-addon-fit", + "version": "0.8.0", + "original": "LICENSE", + "file": "LICENSE-fit", + "source": "https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/LICENSE", + "sha256": "e256f01188af527e4d06d21d06fbf785ae9c50d4b328bf03cbe0ba7f0aa4228f", + "bytes": 1103, + "license": "MIT" + } +] diff --git a/docs/runtime-repair/IMPLEMENTATION_REPORT.md b/docs/runtime-repair/IMPLEMENTATION_REPORT.md new file mode 100644 index 0000000..0a26d1f --- /dev/null +++ b/docs/runtime-repair/IMPLEMENTATION_REPORT.md @@ -0,0 +1,64 @@ +# TianShanOS 定向修复交付(2026-09-24) + +代码已修改;受控主机测试通过;ESP32-S3 构建通过。**板卡验收、真实 SSH 服务器回归、三模型联动和运行资源对比未运行,不能据此宣称可以直接发布。** 本次没有刷机、清配置、停止真实模型、提交或推送。 + +## 基线与范围 + +基线 HEAD:`d6ed947a592265fa12754828bc79803fc50c1db2`。执行用户交付的《TianShanOS_Codex_代码修改交接文档.md》v1.0;此前证书修复保留。开工 SHA 核对表中,证书、HTTPS、时间、PKI、通用服务管理器等文件均未再改动;共同修改的 app.js 和中英语言文件通过既有证书 UI 回归。工作期间其他任务修改了首页、路由、终端、提示文案等 Web 文件,均保留,不能把这些更改全算成本轮修复。 + +关键模块原本为 C,仍保持 C ABI;新公共头文件有 C++ linkage guard。未增加 C++ 运行时、线程框架、全局 JSON allocator hook、后台健康守护或新分区。 + +## 实现及原因 + +| 批次 | 最终行为 | 主要文件 | +|---|---|---| +| A 日志 | 原始串口记录用独立 va_copy 完整输出一次;缓存用两个固定槽生成有截断标识的 UTF-8/ANSI 预览。抢不到槽/锁计数降级;回调和输出不持环形锁;移除私钥前缀、完整凭据命令/执行输出诊断,第三方认证噪声降 DEBUG | ts_log.c、ts_log_preview.h、SSH/client/action/vendor 日志 | +| B 规则所有权、提交 | 不再 delete+add 编辑。候选完整准备后,以 expected_revision 比较提交;旧执行持有原配置 lease,提交后重新核对代次才准入。全局最多一个退役负载;编辑门禁串行候选。持久化前短锁复制标量视图,动态负载由编辑门禁保持有效 | ts_rule_engine.c、ts_rule_codec.c、ts_rule_store.c、ts_api_automation.c、ts_cmd_auto.c | +| C 产品语义 | show_on_dashboard 与 manual_trigger、allow_manual_trigger、enabled 分离;手动保留自动条件。保存不启动,自动恢复由下一轮正常评估处理。模型状态以后台服务记录/远端证据为准,未知禁止盲启动;自动模式停止有再次自动启动提示 | app.js、语言文件、ts_ssh_service.c、ts_action_manager.c | +| D SSH/监控 | 槽位+代次句柄,先登记再运行,协作取消,worker 自行释放。共同连接入口认证前验证 known_hosts;交互确认必须带当前完整指纹。TCP、握手、认证、exec、读写/关闭共享各操作总 deadline,EAGAIN 等待不超过 100ms | ts_ssh_client.c、ts_ssh_log_watch.c、ts_ssh_probe.c、API/CLI 调用者 | +| E 回归/工件 | 主机故障注入、并发屏障、实际函数 UI 测试、目标构建;SPIFFS 显式依赖 Web 压缩完成,资源版本更新 | tests/runtime、ts_webui/CMakeLists.txt、index.html | + +另外修复了同步动作等待超时后的结果对象生命周期:等待者和执行者各持引用,后台不会继续写入已经失效的调用栈。SSH API 的凭据改为请求局部生命周期,避免并发请求共享/释放同一密钥。它们直接服务于本轮并发和 SSH 调用链的可靠性。 + +## 契约与使用边界 + +- 旧客户端缺少 expected_revision 时不能静默覆盖。冲突保留草稿;网络中断后只读回核实,不自动重放保存。显式 false 与字段缺省有区别;模板解析失败保留引用,不能凭猜测把后台规则变成卡片。 +- 规则读者 acquire/release;入队动作持有模板、主机和 SSH 命令的执行快照。运行中改身份/删除被拒绝,改展示或模式不撤销已受理执行。确认停止后允许重新绑定。 +- 普通 SD JSON 使用 pending/previous 文件、NVS 阶段标记、读回校验和恢复;NVS-only 使用双 bank 和最终选择标记。权威提交不确定时停止自动准入。镜像失败明确返回已应用但备份未同步,不回退到陈旧 NVS。 +- 同名加密 `.tscfg`、旧单文件 `rules.json` 和缺 SD 时的镜像来源维持只读,修改前报错;不解密降级、不删除旧配置。不是所有历史格式都可以直接网页编辑。 +- 服务记录最多 64 项(既有 SSH 命令上限),以命令 ID、配置目标 host/port、受管路径保护实例;远端启动前查询,并用原子 mkdir 锁目录避免失联后重复启动。主机别名不会自动合并为物理机器身份;远端同一路径锁仍约束同名实例。 +- 新受管进程用独立 session/process group,记录准确 PID 和 `/proc` 启动时间;停止只在核对身份后 TERM 该组,确认后才 stopped。删除了 PID-1 猜测。**旧固件只有单 PID、无法证明身份的活跃进程可以显示运行,但拒绝自动误杀;需操作人员确认旧实例退出,再由新版本接管。** 这是安全兼容边界,未擅自迁移现场进程。 +- 停 watcher 仅取消观察;迟到 READY 受服务 generation 阻挡。ready 是历史日志证据,不代表持续 HTTP 推理健康。启动 exec 后断线、监控创建失败或停止结果未知都显示 unknown。 +- 无新常驻任务。watcher 仍为 8KiB 栈、core 1、priority 5;默认查询/日志轮询频率未提高;页面隐藏、重复请求、已移除弹窗的迟到响应受控。 +- 普通 SSH exec 默认每个输出流最多 64KiB,watcher 为 128B;溢出返回错误。大文件应走原文件传输接口。交互 shell、SFTP/SCP 仍需真实服务端回归,不以编译代替运行验证。 +- **DNS 是例外边界**:lwIP `gethostbyname()` 同步调用仍受原生解析重试约束,无法在其内部做到 100ms 取消。返回后立即检查总 deadline。已核对 SDK 默认 DNS_MAX_RETRIES=4、DNS tick=1s;多服务器/重试的实际耗时未测,不承诺 DNS 也在一个轮询间隔内退出。 +- 显式“日志动作”仍会记录用户要求的文本;本轮移除的是内部诊断泄露,不提供任意用户日志内容的全局秘密识别器。 + +## 静态资源核算(目标工具链,非板卡测量) + +从最终 ELF DWARF 读取 sizeof;旧类型由 HEAD 头文件使用同一 Xtensa 编译器编译对象验证。详见 `evidence/resource-sizeof.txt`。 + +| 项目 | 基线 → 本轮 / 静态值 | +|---|---| +| rule 结构 | 224 → 240B,+16B/条 | +| 每条额外所有权记录 | payload 16B(PSRAM)+ meta 3B;连同结构增量共 35B/条,未含 allocator 自身开销,低于 64B 设计目标 | +| action 结构 | 984 → 992B,+8B/动作;执行专用字段不序列化 | +| 日志固定捕获工作区 | 1624B,共两个槽,低于 2048B | +| watcher 固定槽表 | 32 × 24 = 768B 内部 RAM | +| 规则上下文 | 共 160B(包含原有字段);meta 已含其中 96B | +| 服务登记表 | 64 × 240 = 15360B,指定 PSRAM,失败不回退到内部 RAM | +| 新同步对象 | 按 7 个相关 mutex 的全部容量保守计 7 × 92 = 644B;实际部分是原有锁 | +| 动作队列 | 每项 1032B,16 项;结构增长连同对齐保守计增量不超过 256B | +| 其他控制 | guard 100B、回调任务表 32B、指针/原子/锁控制保守预留 256B | +| 新增常驻内部上界估算 | 1624+768+160+644+256+100+32+256 = **3840B**;特意把部分旧容量也计入。低于 8KiB 目标;链接器整体变化与运行堆仍不能由此推定 | +| 新增常驻任务 | 0(静态任务创建路径审查);实机任务数未测 | + +临时空间按实际上限计算,不把 PSRAM 当无限内存:令 C/A 为一条规则条件/动作数,各不超过 255。一个配置负载约 `16 + 144*C + 992*A`;一个冻结执行约 `992*A + 2368*S`,S 为需绑定的 SSH 动作数。每个同步结果 288B PSRAM 加现有二值信号量;watcher 配置 616B PSRAM,探测命令缓冲 3072B PSRAM,不增加栈。API 候选、引擎规范化候选、一个退役负载与实际执行快照可能同时存在;每次提交还有最多 `32*240=7680B` 的标量持久化视图。队列仍上限 16,退役配置全局上限 1,编辑候选门禁 1。JSON 使用工程已有 allocator,序列化的临时内存另计;分配失败明确拒绝,不无限回退内部 RAM。255 个动作的极限配置不保证在实际剩余内存下装得下。 + +NVS 分区维持 **48KiB**,还与证书/密钥/其他配置共享。双 bank 的最低数据量约为两份配置 JSON 加两份 bank metadata 和 guard,再加 NVS 页/条目/GC 开销,**不能承诺 32 条任意大规则都能放入 NVS**。模拟测试覆盖写失败时保留旧版或拒绝不确定恢复的语义;实际满容量、剩余空间、擦写耗时和断电未测。SD 权威保存后的镜像容量不足会显示“已保存,备份未同步”;NVS-only staging 空间不足拒绝新提交。未扩大分区。R01 保留未验收。 + +## 构建、工件与下一步 + +使用 ESP-IDF v5.5.2、本机 Python 3.12 环境和仓库 `tools/build.sh`,目标 ESP32-S3。分区和发布版本未擅自升级;dirty 构建版本仅作定位。工件清单、SHA-256、大小见 `evidence/artifacts.json`,文件位于 `build/runtime-repair-20260924/`。二进制是本地待验收工件,包含既有证书补丁及保留的其他 Web 改动。 + +测试命令与每项验收映射见 [VERIFICATION.md](VERIFICATION.md)。交付前仅检查源码/主机/构建,不做现场操作;批准设备测试后,按 E01/E02/R01 和未运行项在同板卡、同配置下完成回归,尤其是真实 Linux 进程组停止、SSH 共同调用者及断电恢复。 diff --git a/docs/runtime-repair/REVIEW_FIXES_REPORT.md b/docs/runtime-repair/REVIEW_FIXES_REPORT.md new file mode 100644 index 0000000..9421603 --- /dev/null +++ b/docs/runtime-repair/REVIEW_FIXES_REPORT.md @@ -0,0 +1,57 @@ +# 两轮 Reviewer 问题修复记录 + +2026-09-24,基于 HEAD d6ed947 的现有工作树,保留先前证书修复及其他并行页面改动。本轮完成 8 项定向修复和用户追加的交叉约束;本机回归与 ESP32-S3 构建通过。未刷机、清配置、提交或推送,不将本机通过称为实机验收通过。 + +## 修改与验收映射 + +| 项目 | 最终行为 | 主要验证 | +|---|---|---| +| R1 查询取消导致永久 busy | 登记身份、运行代次和操作凭证分开;旧结果丢弃,但自己的占用必须完成释放 | service_protocol:连接期间取消、后续查询/停止;旧 finish 不释放新查询占用 | +| R2 断网丢失 ready | 保存本次启动身份及日志就绪证据;仅同一实例可恢复 ready,换实例必须重新取得证据 | service_protocol:无页面恢复、实例变化、读日志期间换实例、错误启动回执 | +| R3 强删自动化任务 | 协作退出,短延迟等待正常停止;未完成返回 pending/error,重启拒绝;不清空远端管理登记 | stop_protocol:真实顶层 stop/task 与真实 engine;completion:真实队列准入/完成所有权;覆盖延迟和重复执行取消 | +| R4 页面持续 SSH 登录 | 普通状态接口只读缓存;用户明确核实才远端查询;启动前未知状态可先核实 | UI:周期调用不携带 verify;service_protocol:100 次缓存读取零新增连接,恢复预算不变 | +| R5 点号规则重启消失 | 目录加载按实际 .json/.tscfg 后缀识别;不笼统丢弃点号开头文件 | rule_reload:真实保存→加载普通、点号前缀及含 pending 的合法 ID,忽略真正临时文件 | +| R6 删除后登记不回收 | 删除建立门禁;持久配置删除成功后才回收;失败保留登记,旧凭证不能影响复用位置 | configuration_protocol:实际配置写包装;service_protocol:70 次同名不同 ID 重建、旧 pin/删除回执 | +| R7 缺失模板无法修复 | 无活动登记可修复/删除;活动服务登记独立于模板及动作完成状态,并保存启动规则身份 | engine:缺失引用修复/删除、动作已结束但独立服务活动时拒绝;service_protocol:配置丢失后仍保护所属规则 | +| R8 查询与主机修改混用目标 | 配置读取和占用建立共用准入协调;网络连接使用捕获的主机快照,不重读可变 ID | configuration_protocol:真实主机写包装与查询并发,写入被保护且实际连接原快照 | + +## 协议与产品边界 + +- 登记代次与操作凭证由本次开机内不复用的序号分配,耗尽时拒绝新准入。完成只释放对应占用;运行代次过期只影响结果发布,不影响自身清理。停止/取消使旧就绪证据失效。 +- 删除、命令身份修改、主机身份修改与查询准入共用 binding gate。网络 I/O 不持有该协调锁;配置删除期间登记保持 deleting 门禁,删除失败不回收。快照 pin 带登记身份,旧 unpin 不减新登记的引用。 +- 自动化停止关闭动作准入,最多短等 200ms;调用方和队列/执行者分别持有完成信用,全部归还且评估任务退出才报告停止。长操作仍在结束时返回“正在停止,请稍后重试”,期间 start/resume 不重新放行动作。现有网络超时继续负责结束 I/O,无外部强删。 +- 停止自动化不会停止真实模型,也不会清掉运行中或未知服务的登记。延迟和重复动作会协作结束;已经开始的动作正常释放自己的快照和临时占用。 +- 启动回执包含 Linux boot ID、PID、/proc start ticks。完成阶段必须与回执匹配;日志读取前后都复核同一实例。日志由本次启动重定向清空,不能用旧 ready 文本给新进程背书。 +- 断网恢复复用现有 watcher 容量,最多 3 次远端恢复尝试/启动代次、5 秒间隔、20 秒调度窗口;一次已开始的 I/O 仍受自身超时约束。预算仅在新启动代次建立,不因页面刷新、查询成功或恢复成功补充。资源不足时保留 unknown,不伪报恢复成功。 +- 正常页面显示的是最近一次证据及其时间,不代表持续在线监测。未增加永久远端健康轮询;用户显式核实与启动/停止仍会产生必要连接。 +- 服务独立记录启动规则身份。活动/未知服务所属规则的动作结构变更及删除受保护;名称、显示、手动/自动等不改变动作结构的编辑仍可进行。旧配置失去模板且不能恢复绑定时,保守检查独立服务登记,不以查找失败或动作已返回推断安全。 + +## 本机验证 + +- `bash tests/runtime/run_all.sh`:13 组 PASS,含原回归和新增交叉反例;C 主机测试使用 ASan/UBSan,文件/RTOS/SSH 等外部边界按各测试注明进行模拟。 +- `bash tests/certificate/run_host.sh`:8 组 PASS。日志中的旧 manager bug REPRODUCED 是基线反例,后续修复断言通过。 +- 实际配置写入口删除门禁补充断言、最终 UI VM 检查通过;app/router/terminal JavaScript 语法检查通过。 +- ESP-IDF 5.5.2 / ESP32-S3 构建 PASS,使用既有 Python 3.12 环境,没有 fullclean。固件大小 2,161,568B,app 分区剩余约 31%。 +- 构建结束时源码摘要核对无变化;工作区另有并行 Web 页面编辑,之后若继续变化,不应把该构建视为包含后续编辑。工件目录保存当次 manifest 和哈希。 +- 本轮后端改动的 diff whitespace 检查通过。全工作树 diff --check 仍报告 app.js 其他页面位置的 4 处尾随空白,未修改这些并行改动。详见 evidence/reviewer-fixes/diff-check.txt。 + +## ESP32-S3 资源预算 + +从目标 ELF DWARF 核对(不是主机 sizeof): + +| 项目 | 修复前 | 本轮后 | +|---|---:|---:| +| 服务登记,每条 | 240B | 416B | +| 64 条登记,固定 PSRAM | 15,360B | 26,624B | +| watcher 固定槽,每槽 | 24B | 24B | +| watcher 配置,按需 PSRAM | 616B | 620B | +| 动作绑定快照,按需 PSRAM | 2,368B | 2,372B | +| 规则 / 动作本体 | 240B / 992B | 不变 | + +新增登记 PSRAM 为 11,264B,无每次页面刷新分配或握手;队列 16、watcher 槽 32、规则退役负载上限不变。没有新增常驻任务或独立恢复调度器,恢复任务使用现有 watcher 槽和栈规格。新增固定序号/停止状态与计数为少量标量;实际总堆、短时任务退出重叠、TLS 峰值和栈最低余量仍需板卡测量,不能仅凭此表宣称整体性能验收完成。 + +## 尚未验证 + +未运行真实 ESP32-S3、真实 SSH 模型服务、多浏览器联机压力、三模型启动、Flash 断电或持久化耐久测试。Linux 实例身份/日志绑定路径已做受控反例,尚需在目标主机实测命令执行和停止。建议下一阶段在授权的测试设备验收 CPU、内部堆最低值、最大连续块、任务/栈余量、SSH 连接计数和 UI/API p95。 + +证据:`evidence/reviewer-fixes/`。工件:`build/reviewer-fixes-20260924/`,含固件、Web 镜像、构建日志、源码摘要与 SHA-256。 diff --git a/docs/runtime-repair/VERIFICATION.md b/docs/runtime-repair/VERIFICATION.md new file mode 100644 index 0000000..7527b22 --- /dev/null +++ b/docs/runtime-repair/VERIFICATION.md @@ -0,0 +1,83 @@ +# 验证记录 + +日期:2026-09-24。PASS 只针对列出的环境;PARTIAL 表示已有局部证据但该验收项尚未全部验收。NOT RUN 表示未执行。没有连接板卡或现场服务器。 + +## 可复现命令与测试模型 + +```sh +./tests/runtime/run_all.sh +./tests/certificate/run_host.sh +# 本机 SDK /Users/massif/esp/v5.5.2/esp-idf,使用其 Python 3.12 环境: +./tools/build.sh +``` + +- runtime:9 个套件 PASS,输出在 `evidence/host-tests.log`。源 JS 与中英语言文件语法检查通过。 +- certificate:此前 8 组回归再次运行,输出在 `evidence/certificate-tests.log`。服务停止回归先运行旧实现故障复现,再运行修复实现;旧实现失败为预期结果。 +- 构建:PASS,完整输出在本地工件目录 `target-build.log`;构建结果摘要及工件哈希保存在 evidence。没有执行构建日志给出的 flash 命令。 +- C 使用 ASan/UBSan;并发由 pthread/屏障模拟,不是 ESP32 双核调度。核心算法来自实际源码;I/O 与 RTOS 边界 stub。引擎套件模拟执行/存储接口,分别由 SSH/持久化套件验证这些实现,不能声称端到端固件运行。 +- store:188 次单点失败位置扫描(NVS、SD 两种来源各 94 次)和 79 个模拟崩溃位置。每次期望完整旧版/新版或显式拒绝恢复;部分编号超过实际路径调用次数,是无故障控制,不能全部称作独立失败分支。NVS mock 不模拟实际 flash 页/GC/电源中断。 +- codec:9 类动作、条件、repeat/动作条件、显式 false、整数值 FLOAT 类型保留、缺失模板保留;条件/动作内存失败,以及 encoder 每个 cJSON 分配位置失败。没有枚举所有字段组合的笛卡尔积。 +- SSH:未知/变更主机认证调用数为 0;合法确认可认证;握手、认证、开 channel、exec、读输出、close 六阶段永久 EAGAIN/取消;stderr-only 释放。真实 libssh2 和 lwIP 的失败释放仍需实机。 +- UI:实际函数在 VM 中运行;草稿/冲突/不确定写、双语、模板优先、日志请求防重入、旧 DOM 响应丢弃。没有用静态字符串搜索冒充页面交互测试,也没有把 VM 当浏览器渲染。 + +## 按交接文档映射 + +| 编号 | 状态 | 已有证据与仍未覆盖范围 | +|---|---|---| +| P01 | PARTIAL | UI 函数保存手动条件/类型并单次 update;codec round-trip;真实浏览器卡片布局/切换未运行 | +| P02 | PARTIAL | engine 遍历 enabled/manual/allow 组合;UI 显示由 show 决定;真实页面全部组合未运行 | +| P03 | PARTIAL | codec 缺省/显式 false、引擎兼容解析代码审查;完整历史现场配置未提供 | +| P04 | PARTIAL | 缺失模板序列化保留;UI 模板优先于缓存命令、请求失败 unresolved;启动加载顺序实机未运行 | +| P05 | PASS(主机) | 条件真时 manual 不自动准入,合法手动按 allow/enabled 准入 | +| P06 | PARTIAL | 引擎正常评估准入、保存 handler 无执行调用;真实调度循环未运行 | +| P07 | PARTIAL | 实际 service registry 拒绝重复准入,远端 mock;真实 Linux 锁目录/跨规则同时启动未运行 | +| P08 | PARTIAL | engine expected_revision 冲突、UI 单次带版本 update 和保留草稿;两个真实浏览器未运行 | +| P09 | PARTIAL | 主机/命令/模板/规则共同 binding gate 静态审查;已停止重绑定通过;全部 API 并发场景未运行 | +| C01 | PASS(主机范围) | codec 分配位置失败、engine 候选失败后旧配置/版本保留;生产内存压力未测 | +| C02 | PASS(模拟) | 短写、flush/fsync/close/rename、NVS set/commit/readback 故障扫描,错误传播 | +| C03 | PASS(模拟) | 主存储/镜像阶段故障及恢复检查;真实 NVS 满页/GC 未测 | +| C04 | PASS(模拟) | 不确定 guard/回滚路径不能作为成功;恢复失败不加载规则。真实硬件故障未测 | +| C05 | PASS(模拟) | 79 个模拟中断位置恢复为完整旧/新或 fail-closed;板卡断电 NOT RUN | +| C06 | PARTIAL | SD/NVS commit/load 与只读拒绝测试;完整加密包/旧单文件的设备升级回归未运行 | +| C07 | PARTIAL | 9 类动作及代表性非默认字段、条件/repeat round-trip;现场所有动作字段与保存重启未运行 | +| C08 | PARTIAL | 非法操作符、ID、逻辑 enum、引用/内存错误、probe 溢出测试;所有字段极限与 32 条最大实体容量未穷举 | +| O01 | PASS(主机) | variable getter 屏障中更新:旧判断不准入;执行屏障中更新:旧动作快照有效 | +| O02 | PASS(主机) | 活动执行禁止删除、同 ID 重建 instance 改变、统计不继承;旧代 ready 测试另覆盖 service | +| O03 | PARTIAL | 持有旧执行与新读者时第二个退役提交被拒绝,释放后归零;板卡 100 次高频编辑未运行 | +| L01 | PASS(主机) | 510/511/512/1024/4096 字节原始输出完整,自有日志 4096B 完整,缓存明确截断 | +| L02 | PARTIAL | 4 pthread × 1000 条、槽耗尽计数及锁争用降级;ESP32 双核/同核抢占时序未运行 | +| L03 | PASS(主机) | UTF-8/ANSI/末尾 m/空行及完整回传验证 | +| L04 | PASS(主机范围) | 实际 hook、自有入口、capture 开关、回调递归;init/deinit 与外部 IDF logger 极端并发未运行 | +| L05 | PARTIAL | 共同 client 所有日志级别捕获不含合成密码;静态移除私钥/原始命令诊断;全部 vendor 失败路径未动态执行 | +| W01 | PASS(主机) | task 创建失败、创建后立即 READY/结束,槽登记及释放正确 | +| W02 | PARTIAL | 协作停止/自然退出、资源计数;全部 stop_all/deinit 竞态组合及真机循环未运行 | +| W03 | PASS(主机) | 槽复用后旧句柄不能取消新 worker | +| W04 | PARTIAL | 间隔 notify 取消与 client 六阶段 deadline/cancel 测试;真实 TCP/DNS 丢包未运行,DNS 不可立即取消 | +| W05 | PASS(主机) | cancel 后旧 generation READY 不改 unknown/stopped | +| W06 | PASS(主机) | stderr-only/error、session/channel/socket/key 测试计数归零;真实库运输层释放需板卡验证 | +| S01 | PASS(主机) | 共同 client 匹配/未知/变更/明确 verifier 的认证门禁 | +| S02 | PARTIAL | API/CLI/自动/watcher/shell 调用点共同入口静态审查与完整编译;各入口真实服务器握手未运行 | +| S03 | PARTIAL | 永久 EAGAIN 不刷新 deadline、取消停止后续工作;真实丢包/DNS 未运行 | +| S04 | PASS(本机 shell) | 实际 C builder + /bin/sh:单引号、空格、前导 -、shell 元字符按字面量,溢出拒绝 | +| S05 | PASS(主机) | 精确 token、重复/前后缀拒绝、FAIL 优先;异常 exec 不当作 ready | +| U01 | PARTIAL | 日志请求串行、旧弹窗响应丢弃、查询错误保守状态;真实页面完整乱序/断网未运行 | +| U02 | PARTIAL | 启动后 watcher 创建失败、registry unknown 禁止盲启动;真实 exec 后断线未运行 | +| U03 | PARTIAL | watcher cancel 保留远端运行,remote stop mock 证据后 stopped;真实进程组 TERM 未运行 | +| U04 | PARTIAL | 自动模式停止提示/后端无永久抑制静态检查;真实用户交互及自动恢复未运行 | +| E01 | NOT RUN | 未连接现场三模型,不启动/停止真实模型,不刷机或设备重启 | +| E02 | PARTIAL | 优化 JS 语法/gzip、资源版本、SPIFFS 重生成哈希一致;设备浏览器实际下载/缓存未运行 | +| R01 | NOT RUN(运行回归) | 目标 sizeof 与静态容量审计完成;下表实机前后数据均缺失 | + +## 同板卡资源表(待设备测试授权/环境) + +| 场景/指标 | 修复前 | 修复后 | 判定 | +|---|---|---|---| +| 空闲面板:内部当前/最小空闲/最大块、PSRAM、DMA | 未测 | 未测 | NOT RUN | +| 页面进出、断网恢复:任务/socket/watcher、堆趋势 | 未测 | 未测 | NOT RUN | +| 32 条无匹配规则:评估 p95、allocation instrumentation | 未测 | 未测 | NOT RUN | +| 100 次模式切换:NVS/SD 时延、最大保存容量、碎片 | 未测 | 未测 | NOT RUN | +| 100 轮安全测试进程 start/stop/timeout/cancel:堆、栈 HWM、socket | 未测 | 未测 | NOT RUN | +| 同配置普通 API p95,解释超过 10% 的退化 | 未测 | 未测 | NOT RUN | +| 三模型链及持续观察:任务栈 HWM、内存/连接稳定性 | 未测 | 未测 | NOT RUN | + +DNS 原生等待、旧单 PID 实例接管、NVS 双 bank 48KiB 共享容量和真实 Linux process group 行为是下一轮优先核验点。没有从旧 0.5.1 串口日志推断本次修复后的任何运行指标。 diff --git a/docs/runtime-repair/baseline-notes.md b/docs/runtime-repair/baseline-notes.md new file mode 100644 index 0000000..00e5fae --- /dev/null +++ b/docs/runtime-repair/baseline-notes.md @@ -0,0 +1,17 @@ +# Gate 0(2026-09-24) + +HEAD d6ed947a592265fa12754828bc79803fc50c1db2。交接文档已完整读取。 +原工作区证书/HTTPS/time/PKI/API/WebUI 补丁及 tests/certificate 保留;开工 diff 和修改文件 SHA 保存在 /tmp/tianshan-runtime-start。原有 output/、tmp/ 不动。未找到额外仓库 AGENTS.md;遵守用户提供约束。 + +实际构建配置目标 esp32s3,SDK /Users/massif/esp/v5.5.2/esp-idf,已有 Python3.12 构建环境;PSRAM OCT/80MHz、内部保留16KiB来自 sdkconfig,未作为硬件检测结果。无板卡采样/现场完整 JSON;使用合成配置。 + +已核实仍存在:卡片 manual 过滤、手动保存丢条件、delete/add 编辑、无 revision、借用指针解锁使用、先 free 再分配、保存错误丢失、日志512截断/共享 scratch、watcher 裸句柄与强删、SSH认证前缺少信任检查、EAGAIN无总deadline。 + +当前规则权威加载优先 SD目录(同名tscfg优先)>旧单文件> NVS。当前 register/enable/delete 全量保存;普通 SD JSON、NVS需要新恢复协议;不可安全写回的加密/旧单文件来源在改内存前拒绝写,不删除或明文降级。 + +调用清单 /tmp/tianshan-runtime-start/{rule,ssh}-callers.txt:规则调用来自自动评估任务、API、CLI、启动加载;SSH来自API/CLI/自动动作/日志监控/shell。API规则详情和导出借用内部指针;规则/模板执行跨网络等待。共同路径修改需逐个回归。 + +批次 A 日志;B 规则所有权与存储;C 字段/UI与服务准入;D SSH生命周期与信任;E 构建和综合验收。原证书修复不作为本轮功能测试替代。 +资源目标:新增常驻任务0,常规评估/日志新增分配0;日志工作区<=2KiB,规则元数据<=64B/条,新增内部常驻<=8KiB。实际sizeof/链接图与实机未测分开记录。 + +收尾核对:开工已有的证书/HTTPS/时间/PKI/服务管理器文件 SHA 保持不变;共同 Web 文件在本轮叠加修改。期间另一任务继续修改 index.html、api.js、app.js、router.js、terminal.js 和语言文件;均保留。最终构建前后源码 SHA manifest 相同,记录于工件目录,不能把这个联合工作区等同于已提交版本。构建生成的 bin 保留为本轮新工件,未刷写。 diff --git a/docs/runtime-repair/evidence/artifacts.json b/docs/runtime-repair/evidence/artifacts.json new file mode 100644 index 0000000..b7ae210 --- /dev/null +++ b/docs/runtime-repair/evidence/artifacts.json @@ -0,0 +1,26 @@ +{ + "TianShanOS.bin": { + "bytes": 2157264, + "sha256": "1b32fa63b196fd97f5e69811ab88bc7758f611b43242c1712a5da4c879f4565f" + }, + "www.bin": { + "bytes": 3145728, + "sha256": "b0fa8484b032e1a457dc2e42faa8b2eb5dce75a7ba4f141464ec270a3e0c4bce" + }, + "bootloader/bootloader.bin": { + "bytes": 22496, + "sha256": "293d3ec188d6246688c6d1d971ece0f7dcc130117cb04be5aa1d36a80550c81f" + }, + "partition_table/partition-table.bin": { + "bytes": 3072, + "sha256": "973dfb7f44bdd42d525e53fcc1eb06ac5745687dddc1c73223715df841d785e5" + }, + "ota_data_initial.bin": { + "bytes": 8192, + "sha256": "7d2c7ac4888bfd75cd5f56e8d61f69595121183afc81556c876732fd3782c62f" + }, + "flasher_args.json": { + "bytes": 1169, + "sha256": "5288d74c7e3ee9e0369f93f9418802ad2b455159cae42f6261c29be818034cc9" + } +} diff --git a/docs/runtime-repair/evidence/build-summary.txt b/docs/runtime-repair/evidence/build-summary.txt new file mode 100644 index 0000000..f144689 --- /dev/null +++ b/docs/runtime-repair/evidence/build-summary.txt @@ -0,0 +1,8 @@ +[1/7] Copying web assets to build directory +TianShanOS.bin binary size 0x20ead0 bytes. Smallest app partition is 0x300000 bytes. 0xf1530 bytes (31%) free. +Bootloader binary size 0x57e0 bytes. 0x2820 bytes (31%) free. +[6/7] Minifying + gzipping web resources +Minifying web resources in /Users/massif/TianshanOS/build/esp-idf/ts_webui/web_optimized... +[7/7] cd /Users/massif/TianshanOS/build/esp-idf/ts_webui && /Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python /Users/massif/esp/v5.5.2/esp-idf/components/spiffs/spiffsgen.py 0x300000 /Users/massif/TianshanOS/build/esp-idf/ts_webui/web_optimized /Users/massif/TianshanOS/build/www.bin --page-size=256 --obj-name-len=32 --meta-len=4 --use-magic --use-magic-len +Project build complete. To flash, run: +✅ 当前固件版本: 0.5.1+d6ed947d.09240429 diff --git a/docs/runtime-repair/evidence/certificate-tests.log b/docs/runtime-repair/evidence/certificate-tests.log new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/runtime-repair/evidence/certificate-tests.log @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/runtime-repair/evidence/host-tests.log b/docs/runtime-repair/evidence/host-tests.log new file mode 100644 index 0000000..d26733e --- /dev/null +++ b/docs/runtime-repair/evidence/host-tests.log @@ -0,0 +1,9 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/runtime-repair/evidence/resource-sizeof.txt b/docs/runtime-repair/evidence/resource-sizeof.txt new file mode 100644 index 0000000..1455fc3 --- /dev/null +++ b/docs/runtime-repair/evidence/resource-sizeof.txt @@ -0,0 +1,16 @@ +Xtensa ESP32-S3 ELF DWARF sizeof (bytes), SDK 5.5.2 +s_capture: 1624 +watch slots: 768 +service_t: 240 +ts_auto_rule_t: 240 +ts_auto_action_t: 992 +ts_action_queue_entry_t: 1032 +rule context: 160 +rule meta array: 96 +StaticSemaphore_t: 92 +action_completion_t: 288 +action_binding_t: 2368 +ts_auto_condition_t: 144 +rule_payload_t: 16 +watch config: 616 +Baseline HEAD same target compiler: rule=224, action=984 bytes diff --git a/docs/runtime-repair/evidence/reviewer-fixes/build-source-check.txt b/docs/runtime-repair/evidence/reviewer-fixes/build-source-check.txt new file mode 100644 index 0000000..d3282fc --- /dev/null +++ b/docs/runtime-repair/evidence/reviewer-fixes/build-source-check.txt @@ -0,0 +1 @@ +Source changes during build: [] diff --git a/docs/runtime-repair/evidence/reviewer-fixes/certificate.log b/docs/runtime-repair/evidence/reviewer-fixes/certificate.log new file mode 100644 index 0000000..9512e4e --- /dev/null +++ b/docs/runtime-repair/evidence/reviewer-fixes/certificate.log @@ -0,0 +1,9 @@ +PASS UTC/serial bounds and bounded retry/control policy +PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots +PASS UI: error typing, bilingual/fallback, text output, uncertain POST, button recovery, refresh separation +PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA +PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors +PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation +PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked) +REPRODUCED manager stop bug: callback failure becomes success/stopped +PASS manager stop/restart: failed stop retained, restart aborted, successful/duplicate stop unchanged diff --git a/docs/runtime-repair/evidence/reviewer-fixes/configuration.log b/docs/runtime-repair/evidence/reviewer-fixes/configuration.log new file mode 100644 index 0000000..81c5541 --- /dev/null +++ b/docs/runtime-repair/evidence/reviewer-fixes/configuration.log @@ -0,0 +1 @@ +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement diff --git a/docs/runtime-repair/evidence/reviewer-fixes/resource-sizeof.txt b/docs/runtime-repair/evidence/reviewer-fixes/resource-sizeof.txt new file mode 100644 index 0000000..b39e0b1 --- /dev/null +++ b/docs/runtime-repair/evidence/reviewer-fixes/resource-sizeof.txt @@ -0,0 +1,7 @@ + +warning: Section .debug_aranges in /Users/massif/TianshanOS/build/TianShanOS.elf entry at offset 56 debug_info_offset 3221684224 does not exists, ignoring .debug_aranges. +$1 = 416 +$2 = 24 +$3 = 620 +$4 = 2372 +$5 = 168 diff --git a/docs/runtime-repair/evidence/reviewer-fixes/runtime.log b/docs/runtime-repair/evidence/reviewer-fixes/runtime.log new file mode 100644 index 0000000..616b71a --- /dev/null +++ b/docs/runtime-repair/evidence/reviewer-fixes/runtime.log @@ -0,0 +1,13 @@ +PASS actual log hook/parser: full 510..4096 output, bounded UTF-8 preview, ANSI, concurrent capture/drop, full own output, callback recursion, capture toggle +PASS rule codec: nine action types, conditions/repeats/explicit false, allocation failures, unsupported operator; rule=256 action=1000 +PASS actual rule persistence: NVS and SD fault injection, recovery boundaries, read-only rejection +PASS actual rule engine: revisions/no-op/allocation failures, stale-evaluation barrier, pinned old execution, retirement bound, enable/manual/allow matrix, recreate identity +PASS actual SSH client: pre-auth trust gate, six EAGAIN phase deadlines/cancellation, stderr-only cleanup, bounded wait +PASS actual service registry + watcher: duplicate admission, task failure, immediate finish, stale handle, cooperative cancellation, late READY rejection, truthful remote stop/unknown +PASS service protocol: stale credentials, cancellation cleanup, deletion barrier/failure/reuse, 70 replacements, missing config protection, physical identity, page-free recovery, 3-attempt budget, zero-I/O cached reads +PASS production synchronous action completion: timeout then late result, success, queue rejection; semaphore lifetime balanced +PASS actual configuration wrappers: host edit vs query, immutable target, failed delete preserves registration, successful delete then same-name replacement +PASS actual store -> current loader: normal/dot IDs, temporary files ignored, reload retains saved rule +PASS actual automation stop + engine: blocked action returns normally, leases/executing clear, async work prevents restart, independent remote ownership retained +PASS actual probe builder: quotes, spaces, leading dash, literal shell metacharacters, fail priority, exact tokens, overflow +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/runtime-repair/evidence/reviewer-fixes/ui-final.log b/docs/runtime-repair/evidence/reviewer-fixes/ui-final.log new file mode 100644 index 0000000..aa17785 --- /dev/null +++ b/docs/runtime-repair/evidence/reviewer-fixes/ui-final.log @@ -0,0 +1 @@ +PASS actual UI functions: bilingual states, one revisioned update, manual conditions/types, inline fields/repeat preservation, explicit false vs omitted, conflict/draft/uncertain write diff --git a/docs/runtime-repair/evidence/web-artifact-check.txt b/docs/runtime-repair/evidence/web-artifact-check.txt new file mode 100644 index 0000000..3436368 --- /dev/null +++ b/docs/runtime-repair/evidence/web-artifact-check.txt @@ -0,0 +1,3 @@ +PASS: optimized JavaScript syntax; gzip matches optimized originals; resource version 20260924-prompts-runtime; regenerated SPIFFS bytes identical to build/www.bin. +PASS: modified source SHA manifest stable during final build. +NOT RUN: browser downloading these resources from ESP32. diff --git a/main/ts_core_init.c b/main/ts_core_init.c index 00b77ec..d309304 100644 --- a/main/ts_core_init.c +++ b/main/ts_core_init.c @@ -21,6 +21,26 @@ static const char *TAG = "ts_core"; static bool s_core_initialized = false; static bool s_core_started = false; +static bool s_core_cleanup_pending; +static bool s_core_stopping; + +static esp_err_t core_release_components(void) +{ + esp_err_t ret; + if (ts_service_is_initialized() && (ret = ts_service_deinit()) != ESP_OK) return ret; + if (ts_event_is_initialized() && (ret = ts_event_deinit()) != ESP_OK) return ret; + if (ts_log_is_initialized() && (ret = ts_log_deinit()) != ESP_OK) return ret; + if (ts_config_is_initialized() && (ret = ts_config_deinit()) != ESP_OK) return ret; + return ESP_OK; +} +static esp_err_t core_init_rollback(esp_err_t original) +{ + s_core_cleanup_pending=true; + esp_err_t ret=core_release_components(); + if(ret!=ESP_OK)return ret; + s_core_cleanup_pending=false; + return original; +} /* ============================================================================ * cJSON PSRAM 内存钩子 - 减少 DRAM 碎片 @@ -61,7 +81,7 @@ esp_err_t ts_core_init(void) { esp_err_t ret; - if (s_core_initialized) { + if (s_core_initialized || s_core_cleanup_pending) { ESP_LOGW(TAG, "Core already initialized"); return ESP_ERR_INVALID_STATE; } @@ -112,8 +132,7 @@ esp_err_t ts_core_init(void) ret = ts_log_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize log: %s", esp_err_to_name(ret)); - ts_config_deinit(); - return ret; + return core_init_rollback(ret); } // 3. 初始化事件系统 @@ -121,9 +140,7 @@ esp_err_t ts_core_init(void) ret = ts_event_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize event: %s", esp_err_to_name(ret)); - ts_log_deinit(); - ts_config_deinit(); - return ret; + return core_init_rollback(ret); } // 3.1 注册 config_file 事件监听器(依赖事件系统) @@ -145,10 +162,7 @@ esp_err_t ts_core_init(void) ret = ts_service_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize service: %s", esp_err_to_name(ret)); - ts_event_deinit(); - ts_log_deinit(); - ts_config_deinit(); - return ret; + return core_init_rollback(ret); } s_core_initialized = true; @@ -159,26 +173,15 @@ esp_err_t ts_core_init(void) esp_err_t ts_core_deinit(void) { - if (!s_core_initialized) { - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGI(TAG, "Deinitializing TianShanOS Core..."); - - // 如果已启动,先停止 - if (s_core_started) { - ts_core_stop(); - } - - // 按相反顺序反初始化 - ts_service_deinit(); - ts_event_deinit(); - ts_log_deinit(); - ts_config_deinit(); - - s_core_initialized = false; - ESP_LOGI(TAG, "TianShanOS Core deinitialized"); - + if (!s_core_initialized && !s_core_cleanup_pending) return ESP_ERR_INVALID_STATE; + s_core_cleanup_pending=true; + esp_err_t ret = ts_core_stop(); + if (ret != ESP_OK) return ret; + /* Earlier stages may already have completed on a previous attempt. */ + ret=core_release_components(); + if(ret!=ESP_OK)return ret; + s_core_initialized=false; + s_core_cleanup_pending=false; return ESP_OK; } @@ -189,6 +192,7 @@ bool ts_core_is_initialized(void) esp_err_t ts_core_start(void) { + if(s_core_stopping || s_core_cleanup_pending) return ESP_ERR_INVALID_STATE; if (!s_core_initialized) { ESP_LOGE(TAG, "Core not initialized"); return ESP_ERR_INVALID_STATE; @@ -232,17 +236,24 @@ esp_err_t ts_core_stop(void) } ESP_LOGI(TAG, "Stopping TianShanOS..."); - - // 发送系统关闭事件 - ts_event_post_sync(TS_EVENT_BASE_SYSTEM, TS_EVENT_SYSTEM_SHUTDOWN, NULL, 0); + esp_err_t ret; + /* A retry continues the same stop intent; do not replay shutdown handlers. */ + if(!s_core_stopping) { + s_core_stopping=true; + ret=ts_event_post_sync(TS_EVENT_BASE_SYSTEM,TS_EVENT_SYSTEM_SHUTDOWN,NULL,0); + if(ret!=ESP_OK){s_core_stopping=false;return ret;} + } // 停止所有服务 - ts_service_stop_all(); + ret = ts_service_stop_all(); + if (ret != ESP_OK) return ret; // 保存配置 - ts_config_save(); + ret = ts_config_save(); + if (ret != ESP_OK) return ret; s_core_started = false; + s_core_stopping=false; ESP_LOGI(TAG, "TianShanOS stopped"); return ESP_OK; diff --git a/main/ts_https_retry.h b/main/ts_https_retry.h new file mode 100644 index 0000000..cf01556 --- /dev/null +++ b/main/ts_https_retry.h @@ -0,0 +1,27 @@ +#ifndef TS_HTTPS_RETRY_H +#define TS_HTTPS_RETRY_H +#include +#include +/* Pure policy shared by the coordinator and host tests. Times are monotonic ms. */ +typedef struct { + uint32_t generation, control; + bool ready; + unsigned failures; + int64_t due_ms; +} ts_https_retry_t; +static inline bool ts_https_retry_due(ts_https_retry_t *r, uint32_t generation, + uint32_t control, bool desired, bool ready, int64_t now) +{ + if (generation != r->generation || control != r->control || (ready && !r->ready)) { + r->failures = 0; r->due_ms = 0; + } + r->generation = generation; r->control = control; r->ready = ready; + return desired && ready && r->failures < 4 && now >= r->due_ms; +} +static inline void ts_https_retry_failed(ts_https_retry_t *r, int64_t now) +{ + static const int delay[] = {1000, 5000, 15000}; + if (r->failures < 3) r->due_ms = now + delay[r->failures]; + ++r->failures; +} +#endif diff --git a/main/ts_services.c b/main/ts_services.c index 93745a0..d45b61c 100644 --- a/main/ts_services.c +++ b/main/ts_services.c @@ -40,6 +40,8 @@ #include "ts_device_ctrl.h" #include "ts_config_file.h" #include "esp_log.h" +#include "esp_timer.h" +#include "ts_https_retry.h" static const char *TAG = "ts_services"; @@ -550,17 +552,17 @@ static esp_err_t security_service_start(ts_service_handle_t handle, void *user_d ts_cert_pki_status_t cert_status; esp_err_t ret = ts_cert_get_status(&cert_status); - if (ret == ESP_OK && cert_status.status != TS_CERT_STATUS_ACTIVATED) { - /* 没有有效证书,启动自动注册 */ + if (ret == ESP_OK && (!cert_status.has_certificate || cert_status.cert_info.validity == TS_CERT_VALIDITY_EXPIRED)) { + /* 缺证书或确实过期才自动注册;待校时/尚未生效不触发替换。 */ ESP_LOGI(TAG, "No valid certificate, starting auto-enrollment..."); ret = ts_pki_client_start_auto_enroll(pki_enroll_callback, NULL); if (ret != ESP_OK) { ESP_LOGW(TAG, "Failed to start auto-enrollment: %s", esp_err_to_name(ret)); } } else if (ret == ESP_OK) { - ESP_LOGI(TAG, "Certificate status: %s (valid for %d days)", + ESP_LOGI(TAG, "Certificate status: %s, time validity: %s", ts_cert_status_to_str(cert_status.status), - cert_status.cert_info.days_until_expiry); + ts_cert_validity_to_str(cert_status.cert_info.validity)); } /* 证书已就绪,现在加载加密的配置文件 (.tscfg) */ @@ -652,166 +654,163 @@ static bool api_service_health(ts_service_handle_t handle, void *user_data) * HTTPS 服务回调 (mTLS) - 事件驱动方式 * ========================================================================== */ -/* HTTPS 服务状态 */ +/* TLS lifecycle has exactly one owner. Events only wake it; no event stack TLS work. */ static struct { - bool pending_init; /* 等待时间同步后初始化 */ - ts_service_handle_t handle; /* 服务句柄 */ -} s_https_state = {0}; + TaskHandle_t task; + ts_event_handler_handle_t time_handler, material_handler; + bool desired; + uint32_t control, completed; + esp_err_t stop_result; +} s_https_state; +static portMUX_TYPE s_https_control_lock = portMUX_INITIALIZER_UNLOCKED; + +static void https_conditions_changed(const ts_event_t *event, void *user_data) +{ + (void)event; (void)user_data; + portENTER_CRITICAL(&s_https_control_lock); + TaskHandle_t task = s_https_state.task; + portEXIT_CRITICAL(&s_https_control_lock); + if (task) xTaskNotifyGive(task); +} -/* 时间同步事件处理器 - 当时间同步完成后初始化 HTTPS */ -static void https_time_sync_handler(const ts_event_t *event, void *user_data) +static esp_err_t https_cleanup(void) { - (void)user_data; - - if (!s_https_state.pending_init) { - return; - } - - ESP_LOGI(TAG, "Time synced, now initializing HTTPS with valid time..."); - - /* 刷新 PKI 状态(使用正确的系统时间) */ - ts_cert_refresh_status(); - - /* 检查 PKI 状态 */ - ts_cert_pki_status_t pki_status; - esp_err_t ret = ts_cert_get_status(&pki_status); - if (ret != ESP_OK || pki_status.status != TS_CERT_STATUS_ACTIVATED) { - ESP_LOGW(TAG, "PKI not activated after time sync, HTTPS disabled"); - s_https_state.pending_init = false; - return; - } - - /* 初始化 HTTPS 服务器 */ - ts_https_config_t config = TS_HTTPS_CONFIG_DEFAULT(); - ret = ts_https_init(&config); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to init HTTPS: %s", esp_err_to_name(ret)); - s_https_state.pending_init = false; - return; - } - - /* 注册默认 API 端点 */ - ret = ts_https_register_default_api(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to register default API: %s", esp_err_to_name(ret)); - s_https_state.pending_init = false; - return; - } - - /* 启动 HTTPS 服务器 */ - ret = ts_https_start(); - if (ret == ESP_OK) { - ESP_LOGI(TAG, "HTTPS server started on port 443 (mTLS enabled) [delayed start]"); - } else { - ESP_LOGE(TAG, "Failed to start HTTPS: %s", esp_err_to_name(ret)); + esp_err_t ret = ts_https_stop(); + if (ret == ESP_OK) ts_https_deinit(); + return ret; +} + +static void https_coordinator(void *arg) +{ + (void)arg; + ts_https_retry_t retry = {0}; + for (;;) { + bool desired; + uint32_t control, completed; + portENTER_CRITICAL(&s_https_control_lock); + desired = s_https_state.desired; + control = s_https_state.control; + completed = s_https_state.completed; + portEXIT_CRITICAL(&s_https_control_lock); + if (!desired) { + if (completed != control) { + esp_err_t ret = https_cleanup(); + portENTER_CRITICAL(&s_https_control_lock); + s_https_state.stop_result = ret; + s_https_state.completed = control; + portEXIT_CRITICAL(&s_https_control_lock); + } + } else if (!ts_https_is_running()) { + ts_cert_pki_status_t status = {0}; + ts_https_config_t config = TS_HTTPS_CONFIG_DEFAULT(); + esp_err_t ret = ts_cert_get_status(&status); + bool ready = ret == ESP_OK && ts_cert_prerequisites(&status, config.require_client_cert); + int64_t now = esp_timer_get_time() / 1000; + if (ts_https_retry_due(&retry, status.generation, control, true, ready, now)) { + const char *stage = "cleanup"; + ret = https_cleanup(); + if (ret == ESP_OK) { stage = "init"; ret = ts_https_init(&config); } + if (ret == ESP_OK) { stage = "default_endpoints"; ret = ts_https_register_default_api(); } + /* Stop intent supersedes this attempt before starting the listener. */ + portENTER_CRITICAL(&s_https_control_lock); + bool current = s_https_state.desired && control == s_https_state.control; + portEXIT_CRITICAL(&s_https_control_lock); + if (ret == ESP_OK && current) { stage = "start"; ret = ts_https_start(); } + if (ret != ESP_OK || !current) { + esp_err_t cleanup = https_cleanup(); + if (cleanup != ESP_OK) { stage = "cleanup"; ret = cleanup; } + if (ret != ESP_OK) { + ts_https_record_error(stage, ret); + ts_https_retry_failed(&retry, esp_timer_get_time() / 1000); + } + } + /* A stop arriving inside TLS start is serviced before its acknowledgement. */ + portENTER_CRITICAL(&s_https_control_lock); + current = s_https_state.desired && control == s_https_state.control; + portEXIT_CRITICAL(&s_https_control_lock); + if (!current) continue; + } + } + uint32_t wait_ms = 5000; + int64_t remaining = retry.due_ms - esp_timer_get_time() / 1000; + if (desired && retry.failures > 0 && retry.failures < 4 && remaining > 0 && remaining < wait_ms) + wait_ms = (uint32_t)remaining; + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(wait_ms)); } - - s_https_state.pending_init = false; +} + +static void https_unregister(ts_event_handler_handle_t *handler) +{ + if (!*handler) return; + esp_err_t ret = ts_event_unregister(*handler); + if (ret == ESP_OK) *handler = NULL; + else ESP_LOGW(TAG, "HTTPS subscription cleanup: %s", esp_err_to_name(ret)); } static esp_err_t https_service_init(ts_service_handle_t handle, void *user_data) { - (void)user_data; - - ESP_LOGI(TAG, "Initializing HTTPS service..."); - s_https_state.handle = handle; - - /* 检查系统时间是否有效(年份 >= 2025) */ - if (ts_time_sync_needs_sync()) { - /* 时间无效,注册事件等待时间同步后再初始化 */ - ESP_LOGI(TAG, "System time invalid (< 2025), waiting for time sync event..."); - s_https_state.pending_init = true; - - /* 注册时间同步事件处理器 */ - ts_event_register(TS_EVENT_BASE_TIME, TS_EVENT_TIME_SYNCED, - https_time_sync_handler, NULL, NULL); - - ESP_LOGI(TAG, "HTTPS init deferred until time sync completes"); - return ESP_OK; /* 非阻塞返回,不影响其他服务 */ - } - - /* 时间有效,直接初始化 */ - ESP_LOGI(TAG, "System time valid, initializing HTTPS immediately..."); - - /* 刷新 PKI 状态 */ - ts_cert_refresh_status(); - - /* 检查 PKI 状态 */ - ts_cert_pki_status_t pki_status; - esp_err_t ret = ts_cert_get_status(&pki_status); - if (ret != ESP_OK || pki_status.status != TS_CERT_STATUS_ACTIVATED) { - ESP_LOGW(TAG, "PKI not activated, HTTPS server will not start"); - ESP_LOGW(TAG, "Use 'pki' command to generate and install certificates"); - return ESP_OK; /* 不是致命错误,继续 */ - } - - /* 初始化 HTTPS 服务器 */ - ts_https_config_t config = TS_HTTPS_CONFIG_DEFAULT(); - ret = ts_https_init(&config); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to init HTTPS: %s", esp_err_to_name(ret)); - return ret; - } - - /* 注册默认 API 端点 */ - ret = ts_https_register_default_api(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to register default API: %s", esp_err_to_name(ret)); - return ret; + (void)handle; (void)user_data; + if (s_https_state.task) return ESP_OK; + esp_err_t ret = ESP_OK; + if (!s_https_state.time_handler) + ret = ts_event_register(TS_EVENT_BASE_TIME, TS_EVENT_TIME_SYNCED, + https_conditions_changed, NULL, &s_https_state.time_handler); + if (ret != ESP_OK) return ret; + if (!s_https_state.material_handler) + ret = ts_event_register(TS_EVENT_BASE_PKI, TS_EVENT_PKI_MATERIAL_CHANGED, + https_conditions_changed, NULL, &s_https_state.material_handler); + if (ret == ESP_OK) { + /* Internal stack: TLS and material reads may touch Flash. Not a PSRAM stack. */ + TaskHandle_t task; + if (xTaskCreate(https_coordinator, "https_coord", 8192, NULL, 5, &task) == pdPASS) { + portENTER_CRITICAL(&s_https_control_lock); + s_https_state.task = task; + portEXIT_CRITICAL(&s_https_control_lock); + return ESP_OK; + } + ret = ESP_ERR_NO_MEM; } - - return ESP_OK; + https_unregister(&s_https_state.material_handler); + https_unregister(&s_https_state.time_handler); + return ret; } static esp_err_t https_service_start(ts_service_handle_t handle, void *user_data) { - (void)handle; - (void)user_data; - - ESP_LOGI(TAG, "Starting HTTPS service..."); - - /* 如果正在等待时间同步,跳过启动(会在事件回调中启动) */ - if (s_https_state.pending_init) { - ESP_LOGI(TAG, "HTTPS start deferred (waiting for time sync)"); - return ESP_OK; - } - - /* 检查是否已初始化 */ - ts_cert_pki_status_t pki_status; - esp_err_t ret = ts_cert_get_status(&pki_status); - if (ret != ESP_OK || pki_status.status != TS_CERT_STATUS_ACTIVATED) { - ESP_LOGW(TAG, "HTTPS server not starting (PKI not activated)"); - return ESP_OK; - } - - ret = ts_https_start(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to start HTTPS: %s", esp_err_to_name(ret)); - return ret; - } - - ESP_LOGI(TAG, "HTTPS server started on port 443 (mTLS enabled)"); - return ESP_OK; + (void)handle; (void)user_data; + if (!s_https_state.task) return ESP_ERR_INVALID_STATE; + portENTER_CRITICAL(&s_https_control_lock); + s_https_state.desired = true; + ++s_https_state.control; + portEXIT_CRITICAL(&s_https_control_lock); + xTaskNotifyGive(s_https_state.task); + return ESP_OK; /* Scheduled; actual listening is reported by ts_https_get_runtime(). */ } static esp_err_t https_service_stop(ts_service_handle_t handle, void *user_data) { - (void)handle; - (void)user_data; - - ESP_LOGI(TAG, "Stopping HTTPS service..."); - - ts_https_stop(); - ts_https_deinit(); - - return ESP_OK; + (void)handle; (void)user_data; + if (!s_https_state.task) return ESP_OK; + portENTER_CRITICAL(&s_https_control_lock); + s_https_state.desired = false; + uint32_t control = ++s_https_state.control; + portEXIT_CRITICAL(&s_https_control_lock); + xTaskNotifyGive(s_https_state.task); + for (unsigned i = 0; i < 300; ++i) { + portENTER_CRITICAL(&s_https_control_lock); + bool done = s_https_state.completed == control; + esp_err_t ret = s_https_state.stop_result; + portEXIT_CRITICAL(&s_https_control_lock); + if (done) return ret; + vTaskDelay(pdMS_TO_TICKS(100)); + } + ts_https_record_error("stop_timeout", ESP_ERR_TIMEOUT); + return ESP_ERR_TIMEOUT; } static bool https_service_health(ts_service_handle_t handle, void *user_data) { - (void)handle; - (void)user_data; - + (void)handle; (void)user_data; return ts_https_is_running(); } diff --git a/sdkconfig b/sdkconfig index c2e19e5..3a04067 100644 --- a/sdkconfig +++ b/sdkconfig @@ -2464,6 +2464,7 @@ CONFIG_TS_SECURITY_MTLS_ENABLE=y CONFIG_TS_SECURITY_TOKEN_EXPIRE_SEC=86400 CONFIG_TS_SECURITY_MAX_SESSIONS=8 CONFIG_TS_SECURITY_PERMISSION_LEVELS=4 +CONFIG_TS_SSH_LOG_WATCH_MAX=32 # end of TianShanOS Security Configuration # diff --git a/tests/certificate/README.md b/tests/certificate/README.md new file mode 100644 index 0000000..6ae2e36 --- /dev/null +++ b/tests/certificate/README.md @@ -0,0 +1,68 @@ +# Certificate repair host tests + +These tests use **production C/JavaScript**, ESP-IDF 5.5.2's bundled mbedTLS 3.6.5 +and cJSON sources. They do not connect to devices or change the host clock. +NVS, ESP heap allocation, event delivery, scheduler and HTTP server sockets are +substitutes. The mbedTLS host configuration is its default configuration, not the +ESP32 hardware configuration. This does not validate hardware TLS or Flash. + +Prerequisites: C compiler with ASan/UBSan, CMake, Node, Python with `cryptography`, +and the existing ESP-IDF checkout. No production credentials are read. Credentials +are generated into the temporary build directory with fixed 2026 validity dates. +Private keys are test-only, temporary, and never printed. + +On this macOS workspace (Command Line Tools avoids requiring changes to Xcode's +license/global selection): + +```sh +export DEVELOPER_DIR=/Library/Developer/CommandLineTools +export IDF_PATH=/Users/massif/esp/v5.5.2/esp-idf +export CERT_MBEDTLS_BUILD=/tmp/tianshan-cert-mbedtls +/Users/massif/.espressif/tools/cmake/3.30.2/CMake.app/Contents/bin/cmake \ + -S "$IDF_PATH/components/mbedtls/mbedtls" -B "$CERT_MBEDTLS_BUILD" \ + -DENABLE_TESTING=OFF -DENABLE_PROGRAMS=OFF -DCMAKE_BUILD_TYPE=Debug +/Users/massif/.espressif/tools/cmake/3.30.2/CMake.app/Contents/bin/cmake \ + --build "$CERT_MBEDTLS_BUILD" -j 6 +./tests/certificate/run_host.sh +``` + +Override `CERT_TEST_PYTHON`, `CERT_TEST_BUILD`, `CERT_MBEDTLS_BUILD`, `IDF_PATH` +as needed. On other systems set `DEVELOPER_DIR` appropriately or remove it. +Nothing is installed globally. The runner recompiles tests with ASan/UBSan; +prebuilt mbedTLS is not sanitizer-instrumented. The application under test is. + +- `test_time_retry.c`: pure UTC conversion, calendar limits, serial output boundaries, + retry schedule and control intent policy. +- `test_material.c`: includes the entire production certificate implementation; + real mbedTLS parses generated PEM and checks keys. Injected heap/parse allocation, + NVS set/commit/read and notification failures; pthread readers/writers; metadata + polling and CSR retention. A failed NVS commit deliberately leaves the mock write + visible, proving the implementation does not assume rollback. +- `test_lifecycle.c`: production HTTPS lifecycle, with mocked server and snapshot + provider. Tests failed URI registration and failed cleanup without losing ownership. +- `test_coordinator.c`: production coordinator on a simulated pthread scheduler and + monotonic clock. Tests retry exhaustion, event duplication, fallback, explicit + stop/restart and stop during an in-flight start. Timing is simulated, not measured + FreeRTOS scheduling or worst-case latency. +- `test_api.c`: production JSON handlers plus the production certificate module and + SDK cJSON. HTTP transport/auth middleware are not exercised. +- `test_time_cancel.c`: production clock notification/readiness and cancellation + functions with mocked syscalls. Tests never call the real `settimeofday`. +- `test_ui.cjs`: executes production functions in Node with DOM/API substitutes; + bilingual keys, text errors, uncertain results, button recovery and refresh errors. + This is not browser layout or real Web UI acceptance. + +`extract_lifecycle.py` extracts unchanged function bodies into the temporary build +folder to avoid compiling unrelated SDK request handlers. It does not reimplement +these functions. Tests fail to compile if the source boundaries change. Full target +compilation separately validates the complete translation units. + +See `docs/CERTIFICATE_FIX_REPORT.md` for all A/B/C/D acceptance mappings, limits, +and the remaining device acceptance procedure. + +`./tests/certificate/test_service_stop.sh` (also included in `run_host.sh`) +reproduces the generic manager defect from HEAD and tests the current production +stop/restart functions with mocked callbacks and event delivery. Failure, timeout, +and invalid-state errors prevent restart; successful and duplicate stops and a +successful restart are covered. The user explicitly approved this minimal scope +extension. No source files are changed by this test. diff --git a/tests/certificate/extract_lifecycle.py b/tests/certificate/extract_lifecycle.py new file mode 100644 index 0000000..7d67bdd --- /dev/null +++ b/tests/certificate/extract_lifecycle.py @@ -0,0 +1,27 @@ +"""Compile production lifecycle without unrelated request handlers and SDK transport internals.""" +from pathlib import Path +import sys +s=Path('components/ts_https/src/ts_https.c').read_text() +end=s.index('esp_err_t ts_https_register_endpoint(') +Path(sys.argv[1]).write_text(s[:end]) +s=Path('main/ts_services.c').read_text() +start=s.index('/* TLS lifecycle has exactly one owner.') +end=s.index('/* ============================================================================\n * Console', start) +Path(sys.argv[1]).with_name('coordinator.inc').write_text(s[start:end]) +s=Path('components/ts_api/src/ts_api_cert.c').read_text() +# Extract helper functions and exactly three unchanged handlers; no alternate implementations. +pieces=[s[s.index('static const char *status_to_display'):s.index('/*===========================================================================*/\n/* API Handlers')]] +for name in ['api_cert_status','api_cert_install','api_cert_install_ca']: + start=s.index('static esp_err_t '+name+'(') + end=s.index('\n}\n',start)+3 + pieces.append(s[start:end]) +Path(sys.argv[1]).with_name('api.inc').write_text('\n'.join(pieces)) +def function(source, declaration): + start=source.index(declaration) + end=source.index('\n}\n',start)+3 + return source[start:end] +s=Path('components/ts_net/src/ts_time_sync.c').read_text() +pieces=[function(s,d) for d in ['static void notify_clock_updated(', 'static void time_sync_notification_cb(', 'esp_err_t ts_time_sync_set_time(', 'bool ts_time_sync_needs_sync(']] +s=Path('components/ts_pki_client/src/ts_pki_client.c').read_text() +pieces.append(function(s,'void ts_pki_client_stop_auto_enroll(')) +Path(sys.argv[1]).with_name('time_cancel.inc').write_text('\n'.join(pieces)) diff --git a/tests/certificate/generate_fixtures.py b/tests/certificate/generate_fixtures.py new file mode 100644 index 0000000..54c2b83 --- /dev/null +++ b/tests/certificate/generate_fixtures.py @@ -0,0 +1,30 @@ +"""Ephemeral test-only P-256 credentials; fixed dates, no production material.""" +from pathlib import Path +from datetime import datetime, timezone +import sys +from cryptography import x509 +from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ec +out = Path(sys.argv[1]); out.mkdir(parents=True, exist_ok=True) +key = ec.generate_private_key(ec.SECP256R1()) +ca_key = ec.generate_private_key(ec.SECP256R1()) +other = ec.generate_private_key(ec.SECP256R1()) +def name(cn): return x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)]) +issuer = name('TianShan isolated test CA') +def cert(label, public, start, end, serial, ca=False): + c = (x509.CertificateBuilder().subject_name(issuer if ca else name('localhost')) + .issuer_name(issuer).public_key(public.public_key()).serial_number(serial) + .not_valid_before(datetime.fromisoformat(start).replace(tzinfo=timezone.utc)) + .not_valid_after(datetime.fromisoformat(end).replace(tzinfo=timezone.utc)) + .add_extension(x509.BasicConstraints(ca=ca, path_length=None), critical=True) + .add_extension(x509.SubjectAlternativeName([x509.DNSName('localhost')]), critical=False)) + if not ca: c = c.add_extension(x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH, ExtendedKeyUsageOID.CLIENT_AUTH]), critical=False) + out.joinpath(label+'.pem').write_bytes(c.sign(ca_key, hashes.SHA256()).public_bytes(serialization.Encoding.PEM)) +cert('ca',ca_key,'2020-01-01','2099-01-01',1,True) +cert('a',key,'2026-01-01','2027-01-01',2) +cert('b',key,'2026-01-01','2027-01-01',3) +cert('future',key,'2050-01-01','2051-01-01',4) +cert('expired',key,'2020-01-01','2021-01-01',5) +cert('wrong',other,'2026-01-01','2027-01-01',6) +out.joinpath('key.pem').write_bytes(key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption())) diff --git a/tests/certificate/run_host.sh b/tests/certificate/run_host.sh new file mode 100755 index 0000000..e9b6f63 --- /dev/null +++ b/tests/certificate/run_host.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -euo pipefail +cd "$(dirname "$0")/../.." +: "${IDF_PATH:=/Users/massif/esp/v5.5.2/esp-idf}" +: "${CERT_TEST_BUILD:=/tmp/tianshan-certificate-tests}" +: "${CERT_MBEDTLS_BUILD:=/tmp/tianshan-cert-mbedtls}" +: "${CERT_TEST_PYTHON:=/Users/massif/.espressif/python_env/idf5.5_py3.12_env/bin/python}" +export DEVELOPER_DIR="${DEVELOPER_DIR:-/Library/Developer/CommandLineTools}" +mkdir -p "$CERT_TEST_BUILD" +"$CERT_TEST_PYTHON" tests/certificate/generate_fixtures.py "$CERT_TEST_BUILD/fixtures" +cc -std=c11 -g -fsanitize=address,undefined -Icomponents/ts_cert/include tests/certificate/test_time_retry.c components/ts_cert/src/ts_cert_time.c -o "$CERT_TEST_BUILD/time_retry" +"$CERT_TEST_BUILD/time_retry" +cc -std=c11 -g -fsanitize=address,undefined -Wno-unused-function -Itests/certificate/stubs -Icomponents/ts_cert/include -I"$IDF_PATH/components/mbedtls/mbedtls/include" tests/certificate/test_material.c components/ts_cert/src/ts_cert_time.c "$CERT_MBEDTLS_BUILD/library/libmbedx509.a" "$CERT_MBEDTLS_BUILD/library/libmbedcrypto.a" -lpthread -o "$CERT_TEST_BUILD/material" +"$CERT_TEST_BUILD/material" "$CERT_TEST_BUILD/fixtures" +node tests/certificate/test_ui.cjs +"$CERT_TEST_PYTHON" tests/certificate/extract_lifecycle.py "$CERT_TEST_BUILD/lifecycle.inc" +cc -std=c11 -g -fsanitize=address,undefined -I"$CERT_TEST_BUILD" -Itests/certificate/stubs -Icomponents/ts_cert/include -Icomponents/ts_https/include -Icomponents/ts_https/src -I"$IDF_PATH/components/mbedtls/mbedtls/include" tests/certificate/test_lifecycle.c -lpthread -o "$CERT_TEST_BUILD/lifecycle" +"$CERT_TEST_BUILD/lifecycle" +cc -std=c11 -g -fsanitize=address,undefined -I"$CERT_TEST_BUILD" -Itests/certificate/stubs -Icomponents/ts_cert/include -Icomponents/ts_https/include -Icomponents/ts_https/src -I"$IDF_PATH/components/mbedtls/mbedtls/include" tests/certificate/test_coordinator.c -lpthread -o "$CERT_TEST_BUILD/coordinator" +"$CERT_TEST_BUILD/coordinator" +cc -std=c11 -g -fsanitize=address,undefined -Wno-deprecated-declarations -I"$CERT_TEST_BUILD" -Itests/certificate/stubs -Icomponents/ts_cert/include -Icomponents/ts_https/include -I"$IDF_PATH/components/mbedtls/mbedtls/include" -I"$IDF_PATH/components/json/cJSON" tests/certificate/test_api.c components/ts_cert/src/ts_cert_time.c "$IDF_PATH/components/json/cJSON/cJSON.c" "$CERT_MBEDTLS_BUILD/library/libmbedx509.a" "$CERT_MBEDTLS_BUILD/library/libmbedcrypto.a" -lpthread -o "$CERT_TEST_BUILD/api" +"$CERT_TEST_BUILD/api" "$CERT_TEST_BUILD/fixtures" +cc -std=c11 -g -fsanitize=address,undefined -I"$CERT_TEST_BUILD" -Itests/certificate/stubs tests/certificate/test_time_cancel.c -lpthread -o "$CERT_TEST_BUILD/time_cancel" +"$CERT_TEST_BUILD/time_cancel" + +./tests/certificate/test_service_stop.sh diff --git a/tests/certificate/stubs/esp_err.h b/tests/certificate/stubs/esp_err.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/esp_err.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/esp_heap_caps.h b/tests/certificate/stubs/esp_heap_caps.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/esp_heap_caps.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/esp_http_server.h b/tests/certificate/stubs/esp_http_server.h new file mode 100644 index 0000000..e72a3f6 --- /dev/null +++ b/tests/certificate/stubs/esp_http_server.h @@ -0,0 +1,18 @@ +#ifndef TEST_HTTP_H +#define TEST_HTTP_H +#include "platform.h" +typedef void *httpd_handle_t; +typedef struct { int dummy; } httpd_req_t; +typedef int httpd_method_t; +#define HTTP_GET 0 +#define HTTP_POST 1 +#define HTTP_PUT 2 +#define HTTP_DELETE 3 +typedef struct { + const char *uri; + httpd_method_t method; + esp_err_t (*handler)(httpd_req_t *); + void *user_ctx; +} httpd_uri_t; +int httpd_register_uri_handler(httpd_handle_t,const httpd_uri_t *); +#endif diff --git a/tests/certificate/stubs/esp_https_server.h b/tests/certificate/stubs/esp_https_server.h new file mode 100644 index 0000000..8aa1f82 --- /dev/null +++ b/tests/certificate/stubs/esp_https_server.h @@ -0,0 +1,10 @@ +#include "esp_http_server.h" +typedef struct { + struct {int server_port,max_open_sockets,recv_wait_timeout,send_wait_timeout,task_caps,stack_size;bool lru_purge_enable,enable_so_linger;} httpd; + uint16_t port_secure; + const uint8_t *servercert,*prvtkey_pem,*cacert_pem; + size_t servercert_len,prvtkey_len,cacert_len; +} httpd_ssl_config_t; +#define HTTPD_SSL_CONFIG_DEFAULT() {0} +int httpd_ssl_start(httpd_handle_t *,httpd_ssl_config_t *); +int httpd_ssl_stop(httpd_handle_t); diff --git a/tests/certificate/stubs/esp_log.h b/tests/certificate/stubs/esp_log.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/esp_log.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/esp_netif.h b/tests/certificate/stubs/esp_netif.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/esp_netif.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/esp_tls.h b/tests/certificate/stubs/esp_tls.h new file mode 100644 index 0000000..fa7b8f2 --- /dev/null +++ b/tests/certificate/stubs/esp_tls.h @@ -0,0 +1 @@ +typedef void esp_tls_t; diff --git a/tests/certificate/stubs/freertos/FreeRTOS.h b/tests/certificate/stubs/freertos/FreeRTOS.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/freertos/FreeRTOS.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/freertos/semphr.h b/tests/certificate/stubs/freertos/semphr.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/freertos/semphr.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/lwip/inet.h b/tests/certificate/stubs/lwip/inet.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/lwip/inet.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/nvs.h b/tests/certificate/stubs/nvs.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/nvs.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/nvs_flash.h b/tests/certificate/stubs/nvs_flash.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/nvs_flash.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/platform.h b/tests/certificate/stubs/platform.h new file mode 100644 index 0000000..edaac6b --- /dev/null +++ b/tests/certificate/stubs/platform.h @@ -0,0 +1,64 @@ +#ifndef CERT_TEST_PLATFORM_H +#define CERT_TEST_PLATFORM_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef int esp_err_t; +#define ESP_OK 0 +#define ESP_FAIL -1 +#define ESP_ERR_INVALID_ARG 0x102 +#define ESP_ERR_INVALID_STATE 0x103 +#define ESP_ERR_INVALID_SIZE 0x104 +#define ESP_ERR_NOT_FOUND 0x105 +#define ESP_ERR_NO_MEM 0x101 +#define ESP_ERR_TIMEOUT 0x106 +#define ESP_ERR_NVS_NOT_FOUND 0x1102 +#define ESP_ERR_NOT_SUPPORTED 0x107 +static inline const char *esp_err_to_name(int e) { return e == 0 ? "ESP_OK" : "TEST_ERROR"; } +#define ESP_LOGI(...) ((void)0) +#define ESP_LOGW(...) ((void)0) +#define ESP_LOGE(...) ((void)0) +#define ESP_LOGD(...) ((void)0) +#define MALLOC_CAP_SPIRAM 1 +#define MALLOC_CAP_8BIT 2 +#define MALLOC_CAP_INTERNAL 4 +#define portMAX_DELAY 0xffffffff +#define TS_TIME_MIN_VALID_YEAR 2025 +#define TS_EVENT_BASE_PKI "ts_pki" +#define TS_EVENT_PKI_MATERIAL_CHANGED 1 +#define NVS_READWRITE 1 +typedef int nvs_handle_t; +typedef pthread_mutex_t StaticSemaphore_t; +typedef pthread_mutex_t *SemaphoreHandle_t; +typedef pthread_mutex_t portMUX_TYPE; +#define portMUX_INITIALIZER_UNLOCKED PTHREAD_MUTEX_INITIALIZER +#define portENTER_CRITICAL(p) pthread_mutex_lock(p) +#define portEXIT_CRITICAL(p) pthread_mutex_unlock(p) +static inline SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t *p) { pthread_mutex_init(p,NULL); return p; } +static inline int xSemaphoreTake(SemaphoreHandle_t p, unsigned t) { (void)t; return pthread_mutex_lock(p)==0; } +static inline int xSemaphoreGive(SemaphoreHandle_t p) { return pthread_mutex_unlock(p)==0; } +void *heap_caps_malloc(size_t n, unsigned caps); +esp_err_t nvs_open(const char *, int, nvs_handle_t *); +void nvs_close(nvs_handle_t); +esp_err_t nvs_get_str(nvs_handle_t,const char *,char *,size_t *); +esp_err_t nvs_set_str(nvs_handle_t,const char *,const char *); +esp_err_t nvs_erase_key(nvs_handle_t,const char *); +esp_err_t nvs_commit(nvs_handle_t); +esp_err_t ts_event_post(const char *, int, const void *,size_t,unsigned); +typedef void *ts_keypair_t; +#define TS_CRYPTO_KEY_EC_P256 1 +esp_err_t ts_crypto_keypair_generate(int,ts_keypair_t *); +esp_err_t ts_crypto_keypair_export_private(ts_keypair_t,char *,size_t *); +void ts_crypto_keypair_free(ts_keypair_t); +typedef void esp_netif_t; +typedef struct { struct { uint32_t addr; } ip; } esp_netif_ip_info_t; +static inline esp_netif_t *esp_netif_get_handle_from_ifkey(const char *p) { (void)p; return NULL; } +static inline int esp_netif_get_ip_info(esp_netif_t *p,esp_netif_ip_info_t *i) { (void)p; (void)i; return ESP_FAIL; } +#endif diff --git a/tests/certificate/stubs/ts_core.h b/tests/certificate/stubs/ts_core.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/ts_core.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/ts_crypto.h b/tests/certificate/stubs/ts_crypto.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/ts_crypto.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/ts_event.h b/tests/certificate/stubs/ts_event.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/ts_event.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/stubs/ts_time_sync.h b/tests/certificate/stubs/ts_time_sync.h new file mode 100644 index 0000000..948df4b --- /dev/null +++ b/tests/certificate/stubs/ts_time_sync.h @@ -0,0 +1 @@ +#include "platform.h" diff --git a/tests/certificate/test_api.c b/tests/certificate/test_api.c new file mode 100644 index 0000000..da84184 --- /dev/null +++ b/tests/certificate/test_api.c @@ -0,0 +1,42 @@ +#define main material_suite +#include "test_material.c" +#undef main +#include "cJSON.h" +#include "ts_https.h" +#define TS_API_ERR_INVALID_ARG 1 +#define TS_API_ERR_INTERNAL 7 +#define TS_API_ERR_NO_MEM 8 +#define TS_LOGI(...) ((void)0) +#define TS_LOGE(...) ((void)0) +typedef struct {int code;const char *error;cJSON *data;} ts_api_result_t; +static void ts_api_result_error(ts_api_result_t *r,int code,const char *e) {r->code=code;r->error=e;} +static void ts_api_result_ok(ts_api_result_t *r,cJSON *d) {r->code=0;r->data=d;} +static ts_https_runtime_t runtime={.port=443,.require_client_cert=true}; +void ts_https_get_runtime(ts_https_runtime_t *r) {*r=runtime;} +#include "api.inc" +static ts_api_result_t invoke(bool ca_input,const char *pem) { + cJSON *params=cJSON_CreateObject();cJSON_AddStringToObject(params,ca_input?"ca_pem":"cert_pem",pem); + ts_api_result_t r={0};int ret=ca_input?api_cert_install_ca(params,&r):api_cert_install(params,&r); + assert((ret==0)==(r.code==0));cJSON_Delete(params);return r; +} +int main(int argc,char **argv) { + assert(argc==2);stored[0]=read_pem(argv[1],"key");a=read_pem(argv[1],"a");b=read_pem(argv[1],"b");ca=read_pem(argv[1],"ca"); + assert(ts_cert_init()==0);ts_api_result_t r=invoke(false,a);assert(r.code==0&&!strcmp(stored[1],a));cJSON_Delete(r.data); + r=invoke(true,ca);assert(r.code==0);cJSON_Delete(r.data); + cJSON *bad[]={NULL,cJSON_Parse("{}"),cJSON_Parse("{\"cert_pem\":3}"),cJSON_Parse("{\"cert_pem\":\"\"}")}; + for(unsigned i=0;i<4;++i){r=(ts_api_result_t){0};assert(api_cert_install(bad[i],&r)!=0&&r.error);cJSON_Delete(bad[i]);} + r=invoke(false,"garbage");assert(r.code!=0&&strstr(r.error,"parse")); + r=(ts_api_result_t){0};assert(api_cert_status(NULL,&r)==0); + assert(cJSON_IsTrue(cJSON_GetObjectItem(r.data,"prerequisites_satisfied"))); + assert(!cJSON_IsTrue(cJSON_GetObjectItem(cJSON_GetObjectItem(r.data,"https"),"running")));cJSON_Delete(r.data); + runtime.running=true;runtime.loaded_generation=status().generation;strcpy(runtime.loaded_certificate_sha256,"ACTIVE-A"); + r=invoke(false,b);assert(r.code==0);cJSON_Delete(r.data); + r=(ts_api_result_t){0};assert(api_cert_status(NULL,&r)==0); + assert(cJSON_IsTrue(cJSON_GetObjectItem(r.data,"restart_required"))); + assert(!strcmp(cJSON_GetObjectItem(cJSON_GetObjectItem(r.data,"https"),"loaded_certificate_sha256")->valuestring,"ACTIVE-A"));cJSON_Delete(r.data); + clock_now=0;r=(ts_api_result_t){0};assert(api_cert_status(NULL,&r)==0); + cJSON *info=cJSON_GetObjectItem(r.data,"cert_info");assert(cJSON_IsNull(cJSON_GetObjectItem(info,"seconds_until_expiry")));assert(!cJSON_IsTrue(cJSON_GetObjectItem(info,"is_valid")));cJSON_Delete(r.data); + ts_cert_deinit();for(int i=0;i<3;++i)free(stored[i]);free(a);free(b);free(ca); + puts("PASS actual cert API handlers: JSON validation, PEM installation, business errors, additive status, active/stored separation"); + return 0; +} diff --git a/tests/certificate/test_coordinator.c b/tests/certificate/test_coordinator.c new file mode 100644 index 0000000..9af37ea --- /dev/null +++ b/tests/certificate/test_coordinator.c @@ -0,0 +1,75 @@ +#define main lifecycle_suite +#include "test_lifecycle.c" +#undef main +#include +#include +#include "../../main/ts_https_retry.h" +typedef void *ts_service_handle_t; +typedef void *ts_event_handler_handle_t; +typedef struct {int id;} ts_event_t; +typedef pthread_t *TaskHandle_t; +typedef int BaseType_t; +#define pdTRUE 1 +#define pdPASS 1 +#define pdMS_TO_TICKS(ms) (ms) +#define TS_EVENT_BASE_TIME "time" +#define TS_EVENT_TIME_SYNCED 1 +static pthread_t worker; +static _Atomic int64_t simulated_ms; +static _Atomic bool allowed; +static _Atomic unsigned created_tasks,subscribed; +static int64_t esp_timer_get_time(void) {return atomic_load(&simulated_ms)*1000;} +static void vTaskDelay(unsigned ticks) {(void)ticks;usleep(1000);} +static unsigned ulTaskNotifyTake(int clear,unsigned ticks) {(void)clear;(void)ticks;usleep(1000);return 0;} +static void xTaskNotifyGive(TaskHandle_t t) {(void)t;} +static void (*task_fn)(void *); +static void *task_entry(void *arg) {(void)arg;task_fn(NULL);return NULL;} +static BaseType_t xTaskCreate(void (*fn)(void *),const char *name,unsigned stack,void *arg,unsigned priority,TaskHandle_t *out) { + (void)name;(void)stack;(void)arg;(void)priority;task_fn=fn;*out=&worker;created_tasks++;assert(!pthread_create(&worker,NULL,task_entry,NULL));return pdPASS; +} +static int ts_event_register(const char *base,int id,void (*handler)(const ts_event_t *,void *),void *data,ts_event_handler_handle_t *out) { + (void)base;(void)id;(void)handler;(void)data;*out=(void *)1;subscribed++;return 0; +} +static int ts_event_unregister(ts_event_handler_handle_t h) {(void)h;subscribed--;return 0;} +static int default_error; +esp_err_t ts_https_register_default_api(void) {if(default_error)return default_error;s_endpoint_count=1;s_endpoints[0]=(ts_https_endpoint_t){.uri="/api/auth/whoami"};return 0;} +esp_err_t ts_cert_get_status(ts_cert_pki_status_t *out) {memset(out,0,sizeof(*out));out->generation=stored_generation;out->time_ready=atomic_load(&allowed);return 0;} +bool ts_cert_prerequisites(const ts_cert_pki_status_t *s,bool ca_required) {(void)ca_required;return s->time_ready;} +#include "coordinator.inc" +static void settle(void) {usleep(30000);} +static void wait_running(bool running) {for(int i=0;i<1000;++i){if(ts_https_is_running()==running)return;usleep(1000);}assert(!"coordinator timeout");} +static void *stop_request(void *unused) {(void)unused;assert(https_service_stop(NULL,NULL)==0);return NULL;} +int main(void) { + assert(https_service_init(NULL,NULL)==0);assert(https_service_init(NULL,NULL)==0);assert(created_tasks==1&&subscribed==2); + assert(https_service_start(NULL,NULL)==0);settle();assert(!ts_https_is_running()); + // No event: low-frequency fallback notices the final prerequisite. + atomic_store(&allowed,true);simulated_ms=5000;wait_running(true); + unsigned count=starts; + for(int i=0;i<100;++i)https_conditions_changed(NULL,NULL);settle();assert(starts==count); + stored_generation=2;settle();ts_https_runtime_t r;ts_https_get_runtime(&r);assert(r.loaded_generation==1); + assert(https_service_stop(NULL,NULL)==0);assert(!ts_https_is_running()); + for(int i=0;i<100;++i)https_conditions_changed(NULL,NULL);simulated_ms=100000;settle();assert(starts==count); + start_error=ESP_FAIL;assert(https_service_start(NULL,NULL)==0);settle();assert(starts==count+1); + simulated_ms=101000;settle();assert(starts==count+2); + simulated_ms=106000;settle();assert(starts==count+3); + simulated_ms=121000;settle();assert(starts==count+4); + simulated_ms=999999;for(int i=0;i<100;++i)https_conditions_changed(NULL,NULL);settle();assert(starts==count+4); + assert(https_service_stop(NULL,NULL)==0);start_error=0; + assert(https_service_start(NULL,NULL)==0);wait_running(true);ts_https_get_runtime(&r);assert(r.loaded_generation==2); + // Stop failure is reported, buffers remain; a subsequent explicit stop recovers. + stop_error=ESP_FAIL;assert(https_service_stop(NULL,NULL)==ESP_FAIL);assert(ts_https_is_running());stop_error=0; + assert(https_service_stop(NULL,NULL)==0);assert(!ts_https_is_running()); + // Initialization and default endpoint failures share the bounded retry policy. + init_error=ESP_ERR_NO_MEM;count=starts;assert(https_service_start(NULL,NULL)==0);settle();ts_https_get_runtime(&r);assert(r.last_error==ESP_ERR_NO_MEM&&!strcmp(r.last_error_stage,"init"));assert(starts==count); + assert(https_service_stop(NULL,NULL)==0);init_error=0;default_error=ESP_FAIL; + assert(https_service_start(NULL,NULL)==0);settle();ts_https_get_runtime(&r);assert(!strcmp(r.last_error_stage,"default_endpoints"));assert(!allocations); + assert(https_service_stop(NULL,NULL)==0);default_error=0; + block_start=true; + assert(https_service_start(NULL,NULL)==0); + for(int i=0;!inside_start&&i<1000;++i)usleep(1000); + assert(inside_start); + pthread_t stopping;pthread_create(&stopping,NULL,stop_request,NULL);settle(); + stored_generation=3;https_conditions_changed(NULL,NULL);block_start=false; + pthread_join(stopping,NULL);assert(!ts_https_is_running());settle();assert(!ts_https_is_running()); + puts("PASS actual coordinator with simulated scheduler: fallback, duplicate events, bounded retries, stop intent, explicit restart, stage errors"); +} diff --git a/tests/certificate/test_lifecycle.c b/tests/certificate/test_lifecycle.c new file mode 100644 index 0000000..84b4d3d --- /dev/null +++ b/tests/certificate/test_lifecycle.c @@ -0,0 +1,46 @@ +/* The build extracts the unmodified production lifecycle section (not a model). + * TLS sockets and certificate snapshot provider are deterministic substitutes. */ +#include "lifecycle.inc" +#include +#include +static _Atomic int init_error,start_error,stop_error,uri_error; +static _Atomic bool block_start, inside_start; +static _Atomic unsigned starts,stops,registrations,allocations; +static _Atomic uint32_t stored_generation=1; +static bool has_ca=true; +static esp_err_t generic_handler(httpd_req_t *r) { (void)r;return ESP_OK; } +esp_err_t ts_cert_get_snapshot(bool require_ca,ts_cert_snapshot_t *out) { + memset(out,0,sizeof(*out));if(init_error)return init_error; + if(require_ca&&!has_ca)return ESP_ERR_INVALID_STATE; + out->key=strdup("key");out->certificate=strdup("cert");if(has_ca)out->ca=strdup("ca"); + out->generation=stored_generation;snprintf(out->certificate_sha256,65,"certificate-%u",stored_generation);++allocations;return ESP_OK; +} +void ts_cert_free_snapshot(ts_cert_snapshot_t *s) {if(s->key)--allocations;free(s->key);free(s->certificate);free(s->ca);memset(s,0,sizeof(*s));} +int httpd_ssl_start(httpd_handle_t *h,httpd_ssl_config_t *c) {(void)c;++starts;inside_start=true;while(block_start)usleep(1000);inside_start=false;if(start_error)return start_error;*h=(void *)1;return ESP_OK;} +int httpd_ssl_stop(httpd_handle_t h) {assert(h);++stops;return stop_error;} +int httpd_register_uri_handler(httpd_handle_t h,const httpd_uri_t *u) {(void)u;assert(h);++registrations;return uri_error;} +static void candidate(void) { + assert(ts_https_init(NULL)==0); + s_endpoints[0]=(ts_https_endpoint_t){.uri="/api/auth/whoami"};s_endpoint_count=1; +} +int main(void) { + ts_https_runtime_t r; + has_ca=false;assert(ts_https_init(NULL)==ESP_ERR_INVALID_STATE);assert(!allocations); + ts_https_config_t config=TS_HTTPS_CONFIG_DEFAULT();config.require_client_cert=false; + assert(ts_https_init(&config)==0);assert(s_ca_chain==NULL);assert(ts_https_start()==0);ts_https_deinit();assert(!allocations); + has_ca=true;init_error=ESP_ERR_NO_MEM;assert(ts_https_init(NULL)==ESP_ERR_NO_MEM);init_error=0; + candidate();start_error=ESP_FAIL;assert(ts_https_start()!=0);assert(!ts_https_is_running());ts_https_deinit();assert(!allocations);start_error=0; + candidate();uri_error=ESP_FAIL;assert(ts_https_start()!=0);assert(!ts_https_is_running());ts_https_deinit();assert(!allocations);uri_error=0; + candidate();assert(ts_https_start()==0);unsigned before=registrations; + for(int i=0;i<100;++i)assert(ts_https_start()==0);assert(registrations==before); + ts_https_get_runtime(&r);assert(r.running&&r.loaded_generation==1); + stored_generation=2;ts_https_get_runtime(&r);assert(r.loaded_generation==1); // stored B cannot impersonate A + stop_error=ESP_FAIL;assert(ts_https_stop()!=0);ts_https_deinit();assert(allocations==1&&s_server&&ts_https_is_running()); + stop_error=0;assert(ts_https_stop()==0);ts_https_deinit();assert(!allocations&&!s_server); + candidate();assert(ts_https_start()==0);ts_https_get_runtime(&r);assert(r.loaded_generation==2&&!strcmp(r.loaded_certificate_sha256,"certificate-2"));ts_https_deinit(); + // Half-start cleanup failure must retain handle/materials without claiming running. + candidate();uri_error=ESP_FAIL;stop_error=ESP_FAIL;assert(ts_https_start()!=0);assert(s_server&&allocations==1&&!ts_https_is_running());ts_https_deinit();assert(s_server&&allocations==1); + stop_error=0;uri_error=0;ts_https_deinit();assert(!allocations&&!s_server); + puts("PASS actual HTTPS lifecycle: init/start/URI/stop failures, retained ownership, duplicate start, loaded generation, optional CA"); + return 0; +} diff --git a/tests/certificate/test_material.c b/tests/certificate/test_material.c new file mode 100644 index 0000000..8483f21 --- /dev/null +++ b/tests/certificate/test_material.c @@ -0,0 +1,131 @@ +#include "platform.h" +#include +static _Atomic int64_t clock_now = 1790121600; /* 2026-09-23 UTC */ +static time_t test_clock(time_t *out) { time_t t = atomic_load(&clock_now); if(out)*out=t; return t; } +static bool fail_alloc; +static void *test_malloc(size_t n) { return fail_alloc ? NULL : malloc(n); } +#include "mbedtls/x509_crt.h" +static bool fail_parse_alloc; +static int test_parse(mbedtls_x509_crt *crt,const unsigned char *pem,size_t len) { + return fail_parse_alloc ? MBEDTLS_ERR_X509_ALLOC_FAILED : mbedtls_x509_crt_parse(crt,pem,len); +} +#define mbedtls_x509_crt_parse test_parse +#define time test_clock +#define malloc test_malloc +#include "../../components/ts_cert/src/ts_cert.c" +#undef mbedtls_x509_crt_parse +#undef malloc +#undef time + +static char *stored[3]; +static unsigned writes, commits, events; +static bool fail_set, fail_commit, fail_read, drop_event; +static int slot(const char *key) { return !strcmp(key,"privkey") ? 0 : !strcmp(key,"cert") ? 1 : !strcmp(key,"ca_chain") ? 2 : -1; } +void *heap_caps_malloc(size_t n,unsigned caps) { (void)caps; return test_malloc(n); } +esp_err_t nvs_open(const char *name,int mode,nvs_handle_t *h) { (void)name;(void)mode;*h=1;return ESP_OK; } +void nvs_close(nvs_handle_t h) { (void)h; } +esp_err_t nvs_get_str(nvs_handle_t h,const char *key,char *out,size_t *len) { + (void)h; int i=slot(key); if(fail_read)return ESP_FAIL; + if(i<0||!stored[i])return ESP_ERR_NVS_NOT_FOUND; + size_t n=strlen(stored[i])+1; + if(!out){*len=n;return ESP_OK;} if(*len=0); + free(stored[i]);stored[i]=strdup(value);return ESP_OK; +} +esp_err_t nvs_erase_key(nvs_handle_t h,const char *key) { + (void)h;int i=slot(key);if(fail_set)return ESP_FAIL; + if(i<0||!stored[i])return ESP_ERR_NVS_NOT_FOUND;free(stored[i]);stored[i]=NULL;return ESP_OK; +} +esp_err_t nvs_commit(nvs_handle_t h) { (void)h;++commits;return fail_commit?ESP_FAIL:ESP_OK; } +esp_err_t ts_event_post(const char *base,int id,const void *data,size_t len,unsigned wait) { + (void)base;(void)id;(void)data;(void)len;(void)wait;++events;return drop_event?ESP_FAIL:ESP_OK; +} +esp_err_t ts_crypto_keypair_generate(int type,ts_keypair_t *key) { + (void)type;mbedtls_pk_context *pk=malloc(sizeof(*pk));if(!pk)return ESP_ERR_NO_MEM; + mbedtls_pk_init(pk);int ret=mbedtls_pk_setup(pk,mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); + if(!ret)ret=mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1,mbedtls_pk_ec(*pk),mbedtls_ctr_drbg_random,&s_ctr_drbg); + if(ret){mbedtls_pk_free(pk);free(pk);return ESP_FAIL;}*key=pk;return ESP_OK; +} +esp_err_t ts_crypto_keypair_export_private(ts_keypair_t key,char *out,size_t *len) { + int ret=mbedtls_pk_write_key_pem(key,(unsigned char *)out,*len);if(ret)return ESP_FAIL;*len=strlen(out)+1;return ESP_OK; +} +void ts_crypto_keypair_free(ts_keypair_t key) {mbedtls_pk_free(key);free(key);} +static char *read_pem(const char *dir,const char *name) { + char path[1024];snprintf(path,sizeof(path),"%s/%s.pem",dir,name);FILE *f=fopen(path,"rb");assert(f); + fseek(f,0,SEEK_END);long n=ftell(f);rewind(f);char *p=malloc(n+1);assert(fread(p,1,n,f)==(size_t)n);p[n]=0;fclose(f);return p; +} +static ts_cert_pki_status_t status(void) { ts_cert_pki_status_t s;assert(ts_cert_get_status(&s)==ESP_OK);return s; } +static void install(const char *p) { assert(ts_cert_install_certificate(p,strlen(p)+1)==ESP_OK); } +static void reload(void) { ts_cert_deinit();assert(ts_cert_init()==ESP_OK); } +static char *a,*b,*ca; +static void *writer(void *arg) { (void)arg;for(int i=0;i<100;++i)install(i%2?a:b);return NULL; } +static void *reader(void *arg) { (void)arg;for(int i=0;i<150;++i){ts_cert_snapshot_t snap;assert(ts_cert_get_snapshot(true,&snap)==ESP_OK);assert(!strcmp(snap.certificate,a)||!strcmp(snap.certificate,b));ts_cert_free_snapshot(&snap);status();}return NULL; } +int main(int argc,char **argv) { + assert(argc==2);a=read_pem(argv[1],"a");b=read_pem(argv[1],"b");ca=read_pem(argv[1],"ca"); + char *key=read_pem(argv[1],"key"),*wrong=read_pem(argv[1],"wrong"),*future=read_pem(argv[1],"future"),*expired=read_pem(argv[1],"expired"); + unsigned n; + ts_cert_op_error_t detail; + assert(ts_cert_install_certificate_ex(a,strlen(a)+1,&detail)!=0&&detail==TS_CERT_OP_NOT_INITIALIZED); + assert(ts_cert_init()==0); + assert(ts_cert_install_certificate_ex(a,strlen(a)+1,&detail)!=0&&detail==TS_CERT_OP_PRIVATE_KEY_MISSING); + stored[0]=strdup(key);reload(); + char csr[2048];size_t csr_len=sizeof(csr); + ts_cert_csr_opts_t opts={.device_id="isolated-test"}; + assert(ts_cert_generate_csr(&opts,csr,&csr_len)==0); + n=writes;for(int i=0;i<100;++i)assert(status().status==TS_CERT_STATUS_CSR_PENDING);assert(writes==n); + install(a); + uint32_t generation=status().generation;n=writes; + install(a);assert(status().generation==generation&&writes==n); + assert(ts_cert_install_certificate_ex(wrong,strlen(wrong)+1,&detail)!=0&&detail==TS_CERT_OP_KEY_MISMATCH); + assert(!strcmp(stored[1],a)&&status().generation==generation); + assert(ts_cert_install_certificate_ex(a,strlen(a),&detail)!=0&&detail==TS_CERT_OP_INVALID_INPUT); + const char embedded[]={'a',0,'b',0};assert(ts_cert_install_certificate_ex(embedded,sizeof(embedded),&detail)!=0); + assert(ts_cert_install_certificate_ex(" \r\n",5,&detail)!=0&&detail==TS_CERT_OP_INVALID_INPUT); + for(size_t len=3999;len<=4096;++len){char *p=malloc(len);memset(p,'x',len);p[len-1]=0; + assert(ts_cert_install_certificate_ex(p,len,&detail)!=0); + assert(detail==(len>4000?TS_CERT_OP_INPUT_TOO_LARGE:TS_CERT_OP_PEM_PARSE_FAILED));free(p);} + fail_parse_alloc=true;assert(ts_cert_install_certificate_ex(b,strlen(b)+1,&detail)==ESP_ERR_NO_MEM&&detail==TS_CERT_OP_NO_MEMORY);fail_parse_alloc=false; + fail_alloc=true;assert(ts_cert_install_certificate_ex(b,strlen(b)+1,&detail)==ESP_ERR_NO_MEM&&detail==TS_CERT_OP_NO_MEMORY);fail_alloc=false; + assert(!strcmp(stored[1],a)&&status().generation==generation); + fail_set=true;n=events;assert(ts_cert_install_certificate_ex(b,strlen(b)+1,&detail)!=0&&detail==TS_CERT_OP_STORAGE_FAILED);fail_set=false; + assert(events==n&&status().storage_error&&!strcmp(stored[1],a));reload(); + fail_commit=true;n=events;assert(ts_cert_install_certificate_ex(b,strlen(b)+1,&detail)!=0&&detail==TS_CERT_OP_STORAGE_FAILED);fail_commit=false; + assert(events==n&&status().storage_error);/* Mock deliberately persists set despite failed commit. */ + assert(!strcmp(stored[1],b));reload();assert(!strcmp(s_certificate_pem,b));install(a); + assert(!ts_cert_prerequisites(&(ts_cert_pki_status_t){0},true)); + assert(ts_cert_install_ca_chain(ca,strlen(ca)+1)==0);assert(ts_cert_prerequisites(&(ts_cert_pki_status_t){0},false)==false); + ts_cert_pki_status_t ready=status();assert(ts_cert_prerequisites(&ready,true)); + size_t cl=strlen(ca);char *chain=malloc(2*cl+1);strcpy(chain,ca);strcat(chain,ca);assert(ts_cert_install_ca_chain(chain,strlen(chain)+1)==0); + strcat(strcpy(chain,ca),"-----BEGIN CERTIFICATE-----\nBAD\n-----END CERTIFICATE-----\n"); + assert(ts_cert_install_ca_chain_ex(chain,strlen(chain)+1,&detail)!=0&&detail==TS_CERT_OP_PEM_PARSE_FAILED);free(chain); + /* CRLF and no trailing newline are parsed by the SDK's actual mbedTLS. */ + char *crlf=malloc(strlen(a)*2+1),*q=crlf;for(const char *p=a;*p;++p){if(*p=='\n')*q++='\r';*q++=*p;}*q=0;install(crlf);free(crlf); + char *no_nl=strdup(a);no_nl[strlen(no_nl)-1]=0;install(no_nl);free(no_nl);install(a); + n=writes;unsigned c=commits;for(int i=0;i<1000;++i)status();assert(writes==n&&commits==c); + int64_t from=status().cert_info.not_before,to=status().cert_info.not_after; + const char *tz[]={"UTC","CST-8","PST8PDT"};for(unsigned i=0;i<3;++i){setenv("TZ",tz[i],1);tzset();assert(status().cert_info.not_before==from&&status().cert_info.not_after==to);} + clock_now=from-1;assert(status().cert_info.validity==TS_CERT_VALIDITY_NOT_YET_VALID); + clock_now=from;assert(status().cert_info.is_valid);clock_now=to;assert(status().cert_info.is_valid); + clock_now=to+1;assert(status().cert_info.validity==TS_CERT_VALIDITY_EXPIRED&&status().cert_info.days_until_expiry==-1); + clock_now=0;assert(status().status==TS_CERT_STATUS_TIME_UNVERIFIED&&!status().cert_info.is_valid); + clock_now=-1;assert(!status().time_ready);clock_now=1790121600; + install(future);assert(status().status==TS_CERT_STATUS_NOT_YET_VALID);install(expired);assert(status().status==TS_CERT_STATUS_EXPIRED);install(a); + drop_event=true;install(b);assert(status().generation>generation);drop_event=false; + ts_cert_snapshot_t snap;assert(ts_cert_get_snapshot(true,&snap)==0);install(a);assert(!strcmp(snap.certificate,b));assert(snap.generation!=status().generation);ts_cert_free_snapshot(&snap); + pthread_t t1,t2;pthread_create(&t1,NULL,writer,NULL);pthread_create(&t2,NULL,reader,NULL);pthread_join(t1,NULL);pthread_join(t2,NULL); + assert(ts_cert_get_snapshot(true,&snap)==0);generation=status().generation; + assert(ts_cert_generate_keypair()==0);assert(status().generation!=generation&&!status().has_certificate);assert(snap.certificate!=NULL);ts_cert_free_snapshot(&snap); + assert(ts_cert_delete_keypair()==0);assert(!status().has_private_key&&!status().has_certificate); + ts_cert_deinit();free(stored[0]);stored[0]=strdup("broken");assert(ts_cert_init()==0); + assert(ts_cert_install_certificate_ex(a,strlen(a)+1,&detail)!=0&&detail==TS_CERT_OP_PRIVATE_KEY_INVALID); + ts_cert_deinit();fail_alloc=true;assert(ts_cert_init()==ESP_ERR_NO_MEM);fail_alloc=false; + ts_cert_pki_status_t empty;memset(&empty,0xAB,sizeof(empty));assert(ts_cert_get_status(&empty)!=0);assert(!empty.has_certificate&&!empty.cert_info.subject_cn[0]); + ts_cert_deinit();fail_read=true;assert(ts_cert_init()!=0);fail_read=false;assert(!s_private_key_pem&&!s_certificate_pem); + ts_cert_deinit();for(int i=0;i<3;++i)free(stored[i]); + free(a);free(b);free(ca);free(key);free(wrong);free(future);free(expired); + puts("PASS material: real SDK mbedTLS, mocked NVS/allocation/events, state/time/concurrent snapshots"); + return 0; +} diff --git a/tests/certificate/test_service_stop.c b/tests/certificate/test_service_stop.c new file mode 100644 index 0000000..d5e4e0f --- /dev/null +++ b/tests/certificate/test_service_stop.c @@ -0,0 +1,44 @@ +#include "platform.h" +#define TS_SERVICE_STATE_STOPPED 0 +#define TS_SERVICE_STATE_REGISTERED 1 +#define TS_SERVICE_STATE_RUNNING 2 +#define TS_SERVICE_STATE_STOPPING 3 +#define TS_EVENT_BASE_SERVICE "service" +#define TS_EVENT_SERVICE_STOPPED 1 +typedef int ts_service_state_t; +typedef struct {const char *service_name;int old_state,new_state,error_code;} ts_service_event_data_t; +typedef struct {int state;struct {const char *name;unsigned capabilities;int (*stop)(void *,void *);void *user_data;}def;} ts_service_instance_t; +static void set_service_state(ts_service_instance_t *s,int state) {s->state=state;} +static unsigned stopped_events; +int ts_event_post(const char *base,int id,const void *data,size_t len,unsigned timeout) {(void)base;(void)id;(void)data;(void)len;(void)timeout;++stopped_events;return 0;} +#include "service_stop.inc" +typedef ts_service_instance_t *ts_service_handle_t; +#define TS_SERVICE_CAP_RESTARTABLE 1 +static unsigned starts; +static int ts_service_stop(ts_service_handle_t s) {return stop_service_internal(s);} +static int ts_service_start(ts_service_handle_t s) {++starts;s->state=TS_SERVICE_STATE_RUNNING;return ESP_OK;} +#include "service_restart.inc" +static int result; +static int stop_callback(void *s,void *u) {(void)s;(void)u;return result;} +int main(void) { + ts_service_instance_t s={.state=TS_SERVICE_STATE_RUNNING,.def={.name="https",.stop=stop_callback}}; + result=ESP_FAIL;int ret=stop_service_internal(&s); + if(ret!=ESP_FAIL||s.state!=TS_SERVICE_STATE_RUNNING||stopped_events) { + puts("REPRODUCED manager stop bug: callback failure becomes success/stopped");return 2; + } + result=ESP_OK;assert(stop_service_internal(&s)==ESP_OK);assert(s.state==TS_SERVICE_STATE_STOPPED&&stopped_events==1); + assert(stop_service_internal(&s)==ESP_OK&&stopped_events==1); + s=(ts_service_instance_t){.state=TS_SERVICE_STATE_RUNNING,.def={.name="other",.stop=stop_callback}}; + assert(stop_service_internal(&s)==ESP_OK&&s.state==TS_SERVICE_STATE_STOPPED); + s.def.capabilities=TS_SERVICE_CAP_RESTARTABLE; + const int failures[]={ESP_FAIL,ESP_ERR_TIMEOUT,ESP_ERR_INVALID_STATE}; + for(unsigned i=0;i +#include +/* Use the production time information type, bypassing the platform stub header. */ +#include "../../components/ts_net/include/ts_time_sync.h" +#define TS_EVENT_BASE_TIME "ts_time" +#define TS_EVENT_TIME_SYNCED 1 +#define pdMS_TO_TICKS(x) (x) +static struct {ts_time_sync_info_t info;char timezone[32];} s_time_sync; +static time_t clock_value; +static int set_error,event_error; +static unsigned notifications; +static ts_time_sync_info_t delivered; +static time_t read_clock(time_t *p) {if(p)*p=clock_value;return clock_value;} +static int set_clock(const struct timeval *tv,const struct timezone *tz) {(void)tz;if(set_error)return -1;clock_value=tv->tv_sec;return 0;} +int ts_event_post(const char *base,int id,const void *data,size_t length,unsigned wait) { + (void)base;(void)id;(void)wait;assert(length==sizeof(delivered));delivered=*(const ts_time_sync_info_t *)data;++notifications;return event_error; +} +static struct {_Atomic bool enroll_running,stop_requested;} s_client; +static unsigned delays; +static bool finish_on_delay; +static void vTaskDelay(unsigned t) {(void)t;++delays;if(finish_on_delay)s_client.enroll_running=false;} +#define time read_clock +#define settimeofday set_clock +#include "time_cancel.inc" +#undef time +#undef settimeofday +int main(void) { + set_error=1;assert(ts_time_sync_set_time(1790121600000LL,TS_TIME_SOURCE_HTTP)!=0);assert(notifications==0); + set_error=0;assert(ts_time_sync_set_time(1790121600000LL,TS_TIME_SOURCE_HTTP)==0);assert(notifications==1&&delivered.source==TS_TIME_SOURCE_HTTP);assert(!ts_time_sync_needs_sync()); + assert(ts_time_sync_set_time(0,TS_TIME_SOURCE_MANUAL)==0);assert(notifications==2&&delivered.source==TS_TIME_SOURCE_MANUAL);assert(ts_time_sync_needs_sync()); + struct timeval tv={.tv_sec=1790121600};time_sync_notification_cb(&tv);assert(notifications==3&&delivered.source==TS_TIME_SOURCE_NTP); + event_error=ESP_FAIL;assert(ts_time_sync_set_time(1790121600000LL,TS_TIME_SOURCE_HTTP)==0);assert(!ts_time_sync_needs_sync()); + for(unsigned i=0;i<3;++i){const char *tz[]={"UTC","CST-8","PST8PDT"};setenv("TZ",tz[i],1);tzset();clock_value=1735689599;assert(ts_time_sync_needs_sync());clock_value=1735689600;assert(!ts_time_sync_needs_sync());} + s_client.enroll_running=true;ts_pki_client_stop_auto_enroll();assert(s_client.stop_requested&&s_client.enroll_running&&delays==50); + finish_on_delay=true;ts_pki_client_stop_auto_enroll();assert(!s_client.enroll_running); + puts("PASS actual time notifications/UTC readiness and cooperative enrollment stop (syscalls/tasks mocked)"); + return 0; +} diff --git a/tests/certificate/test_time_retry.c b/tests/certificate/test_time_retry.c new file mode 100644 index 0000000..1d14a9f --- /dev/null +++ b/tests/certificate/test_time_retry.c @@ -0,0 +1,47 @@ +#include "ts_cert_time.h" +#include "../../main/ts_https_retry.h" +#include +#include +#include +int main(void) { + int64_t t; + assert(ts_cert_time_utc(1970,1,1,0,0,0,&t)&&t==0); + assert(ts_cert_time_utc(1969,12,31,23,59,59,&t)&&t==-1); + assert(ts_cert_time_utc(9999,12,31,23,59,59,&t)&&t==253402300799LL); + assert(ts_cert_time_utc(2050,1,1,0,0,0,&t)&&t==2524608000LL); + assert(ts_cert_time_utc(2000,2,29,0,0,0,&t)&&t==951782400); + assert(ts_cert_time_utc(2024,2,29,0,0,0,&t)&&t==1709164800); + assert(!ts_cert_time_utc(2100,2,29,0,0,0,&t)); + assert(!ts_cert_time_utc(0,1,1,0,0,0,&t)); + assert(!ts_cert_time_utc(10000,1,1,0,0,0,&t)); + assert(!ts_cert_time_utc(2026,13,1,0,0,0,&t)); + assert(!ts_cert_time_utc(2026,4,31,0,0,0,&t)); + assert(!ts_cert_time_utc(2026,1,1,24,0,0,&t)); + assert(!ts_cert_time_utc(2026,1,1,0,60,0,&t)); + assert(!ts_cert_time_utc(2026,1,1,0,0,60,&t)); + int64_t seconds[]={86399,0,-1,-86400,-86401};int days[]={0,0,-1,-1,-2}; + for(int i=0;i<5;++i)assert(ts_cert_time_days(seconds[i])==days[i]); + assert(!ts_cert_time_ready(1735689599,2025)&&ts_cert_time_ready(1735689600,2025)); + unsigned char bytes[33];memset(bytes,0xff,sizeof(bytes)); + size_t sizes[]={0,1,20,31,32,33}; + for(int i=0;i<6;++i){struct {char hex[65];char guard;} v;v.guard='!'; + assert(ts_cert_hex(bytes,sizes[i],v.hex,sizeof(v.hex))==(sizes[i]>32)); + assert(strlen(v.hex)==2*(sizes[i]<32?sizes[i]:32));assert(v.guard=='!');} + ts_https_retry_t r={0}; + assert(!ts_https_retry_due(&r,1,1,true,false,0)); + assert(ts_https_retry_due(&r,1,1,true,true,0)); + ts_https_retry_failed(&r,0); + for(int i=0;i<100;++i)assert(!ts_https_retry_due(&r,1,1,true,true,999)); + assert(ts_https_retry_due(&r,1,1,true,true,1000));ts_https_retry_failed(&r,1000); + assert(!ts_https_retry_due(&r,1,1,true,true,5999)); + assert(ts_https_retry_due(&r,1,1,true,true,6000));ts_https_retry_failed(&r,6000); + assert(!ts_https_retry_due(&r,1,1,true,true,20999)); + assert(ts_https_retry_due(&r,1,1,true,true,21000));ts_https_retry_failed(&r,21000); + for(int i=0;i<100;++i)assert(!ts_https_retry_due(&r,1,1,true,true,999999)); + assert(ts_https_retry_due(&r,2,1,true,true,999999)); + ts_https_retry_failed(&r,999999); + assert(!ts_https_retry_due(&r,2,2,false,true,9999999)); + for(int i=0;i<100;++i)assert(!ts_https_retry_due(&r,2,2,false,true,99999999)); + assert(ts_https_retry_due(&r,2,3,true,true,99999999)); + puts("PASS UTC/serial bounds and bounded retry/control policy"); +} diff --git a/tests/certificate/test_ui.cjs b/tests/certificate/test_ui.cjs new file mode 100644 index 0000000..5094981 --- /dev/null +++ b/tests/certificate/test_ui.cjs @@ -0,0 +1,42 @@ +const fs = require('node:fs'), vm = require('node:vm'), assert = require('node:assert/strict'); +const source = fs.readFileSync('components/ts_webui/web/js/app.js','utf8'); +function fn(name) { + // Use complete production functions, bounded by the next top-level declaration. + const match = new RegExp('^(?:async )?function '+name+'\\(', 'm').exec(source); + assert(match, name); + const rest = source.slice(match.index); + const next = /\n(?:async )?function \w+\(/.exec(rest); + return next ? rest.slice(0,next.index) : rest; +} +const translations = {}; +for (const lang of ['zh-CN','en-US']) vm.runInNewContext(fs.readFileSync(`components/ts_webui/web/js/lang/${lang}.js`,'utf8'), {i18n:{registerLanguage:(id,d)=>translations[id]=d}}); +let locale = 'zh-CN'; +const elements = new Map(); +function el(id) {if (!elements.has(id)) elements.set(id,{textContent:'',value:'test PEM',disabled:false,style:{},classList:{add(){},remove(){}}});return elements.get(id);} +let posts=0, refreshFail=false, response={code:0}, reject=false; +const ctx = vm.createContext({console, setTimeout:()=>{}, document:{getElementById:el}, window:{}, + t:(key,params={})=>{let v=key.split('.').reduce((o,k)=>o?.[k],translations[locale])??key;return v.replace(/\{(\w+)\}/g,(_,k)=>params[k]??`{${k}}`);}, + api:{certInstall:async()=>{posts++;if(reject)throw new Error('timeout');return response;},certInstallCA:async()=>{posts++;return response;}}, + refreshCertStatus:async()=>{if(refreshFail)throw new Error('refresh failed');} +}); +for(const name of ['certText','certError','certValidity','certExpiry','installCertificate','installCAChain','installCertMaterial'])vm.runInContext(fn(name),ctx); +(async()=>{ + assert.equal(ctx.certError({message:'M',error:'E'},'F'),'M'); + assert.equal(ctx.certError({message:' ',error:'E'},'F'),'E'); + assert.equal(ctx.certError({error:true},'F'),'F'); + assert.equal(ctx.certText('missing.key','fallback'),'fallback'); + for(locale of ['zh-CN','en-US']) { + for(const key of ['none','invalid','time_unverified','not_yet_valid','valid','expired']) assert(!ctx.certValidity(key).includes('pkiRepair.')); + assert(ctx.certValidity(undefined)); + assert.equal(ctx.certExpiry({is_valid:true,days_until_expiry:20}), ''); // old firmware + assert.equal(ctx.certExpiry({validity:'time_unverified',seconds_until_expiry:null}), ''); + assert(!ctx.certExpiry({validity:'expired',seconds_until_expiry:-1}).includes('pkiRepair.')); + response={code:7,error:''};await ctx.installCertificate(); + assert(el('cert-install-result').textContent.includes('{console.error(e);process.exitCode=1;}); diff --git a/tests/prompts/README.md b/tests/prompts/README.md new file mode 100644 index 0000000..97a4fb6 --- /dev/null +++ b/tests/prompts/README.md @@ -0,0 +1,21 @@ +# Prompt and operation-result regressions + +Run from the repository root. The test harness loads the **actual** inline translator in `index.html`, language packs and complete production JavaScript into a VM. It does not import the hand-transcribed reproduction package. + +```sh +npm ci --prefix tests/prompts +npm test --prefix tests/prompts +npm run test:browser --prefix tests/prompts +node tests/certificate/test_ui.cjs +node tests/runtime/test_ui.cjs +``` + +The browser suite requires locally installed Chrome (`channel: 'chrome'`). It serves the actual WebUI on an ephemeral localhost port, intercepts all `/api/` calls, replaces WebSocket with a stub and rejects external requests. Only the terminal retry test supplies local fixture responses for CDN URLs. It does not use device addresses, credentials, firmware, or real commands. The xterm fixture verifies resource recovery and production initialization, not xterm rendering itself. + +No device validation is performed. Real file storage, browser disk download completion, SSH execution, power state, protection, firmware upgrades and embedded resource packaging require separate authorized acceptance. + +`static.test.cjs`: literal/conditional translations, HTML attributes, finite dynamic families and placeholder contracts. `regression.test.cjs`: actual API/UI/terminal functions with controlled network, DOM, time and device-result inputs. `browser.test.cjs`: actual HTML/deferred-script loading, DOM safety, language recovery and terminal CDN retry. Browser screenshots are written under `output/playwright/`. + +During this repair, existing local Acorn/Playwright installations were used through `NODE_PATH`; no dependencies or browser binaries were installed. The public submission summary is in `docs/PROMPT_REPAIR_REPORT.md`. + +`ownership.browser.test.cjs` covers endpoint contracts, startup/navigation ownership, upload generations, modal ownership, out-of-order outcomes, and independent directory refresh. It is included in `test:browser`. diff --git a/tests/prompts/browser.test.cjs b/tests/prompts/browser.test.cjs new file mode 100644 index 0000000..5ff034e --- /dev/null +++ b/tests/prompts/browser.test.cjs @@ -0,0 +1,129 @@ +const {test,before,after}=require('node:test'); +const assert=require('node:assert/strict'); +const http=require('node:http'),fs=require('node:fs'),path=require('node:path'); +const {chromium}=require('playwright'); +const {root}=require('./harness.cjs'); +let server,browser,base; +before(async()=>{ + server=http.createServer((req,res)=>{ + const rel=decodeURIComponent(new URL(req.url,'http://local').pathname),file=path.resolve(root,'.'+(rel==='/'?'/index.html':rel)); + if(!file.startsWith(root+'/')){res.writeHead(403).end();return;} + fs.readFile(file,(e,data)=>{if(e){res.writeHead(404).end();return;}const ext=path.extname(file);res.setHeader('Content-Type',({'.js':'application/javascript','.html':'text/html','.css':'text/css'})[ext]||'application/octet-stream');res.end(data);}); + }); + await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));base=`http://127.0.0.1:${server.address().port}`; + browser=await chromium.launch({channel:'chrome',headless:true}); +}); +after(async()=>{await browser?.close();await new Promise(resolve=>server?.close(resolve));}); +async function pageFor(language='en-US',handler){ + const context=await browser.newContext({locale:language,viewport:{width:1280,height:900}}); + await context.addInitScript(({language})=>{ + localStorage.setItem('ts_language',language); + class Socket {static OPEN=1;static CONNECTING=0;constructor(){this.readyState=0;}send(){}close(){this.readyState=3;}} + window.WebSocket=Socket; + },{language}); + const page=await context.newPage(),errors=[];page.on('pageerror',e=>errors.push(e.message)); + await page.route('**/*',async route=>{ + const u=new URL(route.request().url()); + if(u.origin!==base){await route.abort();return;} + if(u.pathname.startsWith('/api/')){await route.fulfill({json:{code:0,data:{}}});return;} + if(handler&&await handler(route,u))return; + await route.continue(); + }); + return {page,context,errors}; +} +for(const language of ['zh-CN','en-US']){ + test(`${language}: real index cold start, safe toast/file text, current websocket state`,async()=>{ + const {page,context,errors}=await pageFor(language);try{ + const fetched=[];page.on('request',r=>{if(r.url().includes('/js/lang/'))fetched.push(r.url());}); + await page.goto(base);await page.waitForFunction(()=>i18n.isReady()); + assert.equal(await page.evaluate(()=>getLanguage()),language);assert.equal(fetched.length,1); + assert.equal(await page.evaluate(()=>document.getElementById('app').inert),false); + assert(!await page.locator('#login-modal').innerText().then(t=>t.includes('login.'))); + await page.evaluate(()=>{renderWsStatus(false);showToast('\nSecond line','error',10000);}); + assert.equal(await page.locator('#toast img').count(),0);assert((await page.locator('#toast').textContent()).includes('window.injected),undefined); + assert.equal(await page.locator('#ws-status').getAttribute('title'),await page.evaluate(()=>t('network.disconnected'))); + await page.evaluate(()=>{const list=document.createElement('div');list.id='upload-list';document.body.append(list);filesToUpload=[];handleFileSelect({target:{files:[{name:'',size:1}]}});}); + assert.equal(await page.locator('#upload-list img').count(),0); + assert.deepEqual(errors,[]); + fs.mkdirSync('output/playwright',{recursive:true});await page.screenshot({path:`output/playwright/prompt-repair-${language}.png`}); + }finally{await context.close();} + }); + test(`${language}: initial language failure blocks controls and retry recovers`,async()=>{ + let fail=true;const {page,context,errors}=await pageFor(language,async(route,u)=>{if(u.pathname.includes('/js/lang/')&&fail){await route.abort();return true;}return false;}); + try{await page.goto(base);await page.waitForSelector('#language-status button'); + assert.equal(await page.evaluate(()=>i18n.isReady()),false);assert.equal(await page.evaluate(()=>document.getElementById('app').inert),true); + assert.equal(await page.evaluate(()=>{let n=0;window.confirm=()=>{n++;return true;};confirmAction(t('ui.confirmRollback'));return n;}),0); + fail=false;await page.locator('#language-status button').click();await page.waitForFunction(()=>i18n.isReady()); + assert.equal(await page.evaluate(()=>document.getElementById('app').inert),false);assert.deepEqual(errors,[]); + }finally{await context.close();} + }); +} +test('delayed language package and rapid switches keep the latest requested language',async()=>{ + let release,hold=true;const gate=new Promise(r=>release=r); + const {page,context}=await pageFor('en-US',async(route,u)=>{if(u.pathname.endsWith('/zh-CN.js')&&hold){await gate;await route.continue();return true;}return false;}); + try{await page.goto(base);await page.waitForFunction(()=>i18n.isReady()); + await page.evaluate(()=>{window.firstSwitch=selectLanguage('zh-CN');}); + await page.evaluate(()=>selectLanguage('en-US'));release();hold=false; + await page.evaluate(()=>window.firstSwitch);assert.equal(await page.evaluate(()=>getLanguage()),'en-US'); + await page.evaluate(()=>selectLanguage('zh-CN'));assert.equal(await page.evaluate(()=>getLanguage()),'zh-CN'); + assert.equal(await page.locator('#ws-status').getAttribute('aria-label'),await page.evaluate(()=>t('network.disconnected'))); + }finally{release();await context.close();} +}); +test('terminal resource failure presents retry; a rejected cached promise is not reused',async()=>{ + const {page,context,errors}=await pageFor('en-US',async(route,u)=>{if(u.pathname.startsWith('/vendor/')){await route.abort();return true;}return false;});let attempts=0; + try{await page.goto(base);await page.waitForFunction(()=>i18n.isReady()); + page.on('request',r=>{if(r.url().includes('xterm.css'))attempts++;}); + await page.evaluate(()=>{closeLoginModal();return loadTerminalPage();}); + assert((await page.locator('#terminal-container').textContent()).includes('could not be loaded')); + await page.locator('#terminal-container button').click();await page.waitForFunction(()=>document.querySelector('#terminal-container button')); + assert.equal(attempts,2);assert.deepEqual(errors,[]); + }finally{await context.close();} +}); +for(const language of ['zh-CN','en-US']) { + test(`${language}: package confirmation treats names as text and applies only on explicit verified action`,async()=>{ + const {page,context,errors}=await pageFor(language);try{ + await page.goto(base);await page.waitForFunction(()=>i18n.isReady()); + const path="/sdcard/a');window.injected=true;//.tscfg"; + await page.evaluate(path=>{closeLoginModal();window.fixturePath=path;window.calls=[];api.call=async(name,args)=>{calls.push({name,args});return {code:0,data:{success:false,result_message:''}};};showConfigPackApplyConfirm(path,{valid:false});},path); + assert.equal(await page.locator('#config-pack-apply-confirm').count(),0); + await page.evaluate(()=>showConfigPackApplyConfirm(fixturePath,{valid:true,signature:{signer_cn:''}})); + assert.equal(await page.locator('#config-pack-apply-confirm img').count(),0); + await page.locator('#config-pack-apply-button').click(); + await page.waitForFunction(()=>calls.length===1&&!document.getElementById('config-pack-apply-button').disabled); + assert.equal(await page.evaluate(()=>calls[0].args.path),path); + assert.equal(await page.locator('#config-pack-apply-confirm').count(),1); + assert.equal(await page.locator('#toast img').count(),0); + await page.evaluate(()=>{toastDeadline=0;api.call=async()=>({code:0,data:{success:true,applied_modules:['fixture']}});}); + await page.locator('#config-pack-apply-button').click();await page.waitForFunction(()=>!document.getElementById('config-pack-apply-confirm')); + assert.equal(await page.evaluate(()=>window.injected),undefined);assert.deepEqual(errors,[]); + }finally{await context.close();} + }); +} +test('initial delayed language keeps controls inert until the real package arrives',async()=>{ + let release;const gate=new Promise(r=>release=r); + const {page,context,errors}=await pageFor('en-US',async(route,u)=>{if(u.pathname.endsWith('/en-US.js')){await gate;await route.continue();return true;}return false;}); + try{await page.goto(base,{waitUntil:'domcontentloaded'}); + assert.equal(await page.evaluate(()=>i18n.isReady()),false);assert.equal(await page.evaluate(()=>document.getElementById('app').inert),true); + release();await page.waitForFunction(()=>i18n.isReady());assert.deepEqual(errors,[]); + }finally{release();await context.close();} +}); +test('failed language switch preserves the loaded language; retry clears failure and stale toast',async()=>{ + let fail=true;const {page,context,errors}=await pageFor('en-US',async(route,u)=>{if(u.pathname.endsWith('/zh-CN.js')&&fail){await route.abort();return true;}return false;}); + try{await page.goto(base);await page.waitForFunction(()=>i18n.isReady()); + await page.evaluate(()=>{showToast('old language','info',10000);return selectLanguage('zh-CN');}); + assert.equal(await page.evaluate(()=>getLanguage()),'en-US');assert.equal(await page.evaluate(()=>document.getElementById('app').inert),false); + fail=false;await page.locator('#language-status button').click();await page.waitForFunction(()=>getLanguage()==='zh-CN'); + assert.equal(await page.locator('#toast').evaluate(e=>e.classList.contains('show')),false);assert.deepEqual(errors,[]); + }finally{await context.close();} +}); +test('terminal can initialize after failed resource load using newly served resources',async()=>{ + let fail=true; + const {page,context,errors}=await pageFor('en-US',async(route,u)=>{if(fail&&u.pathname.startsWith('/vendor/')){await route.abort();return true;}return false;}); + try{await page.goto(base);await page.waitForFunction(()=>i18n.isReady());await page.evaluate(()=>{closeLoginModal();return loadTerminalPage();}); + assert.equal(await page.locator('#terminal-container button').count(),1); + fail=false;await page.locator('#terminal-container button').click();await page.waitForSelector('#terminal-container .xterm'); + assert(await page.evaluate(()=>webTerminal.terminal instanceof Terminal&&!!webTerminal.fitAddon)); + assert.equal(await page.locator('#terminal-container button').count(),0);assert.deepEqual(errors,[]); + }finally{await context.close();} +}); diff --git a/tests/prompts/harness.cjs b/tests/prompts/harness.cjs new file mode 100644 index 0000000..0bfa21a --- /dev/null +++ b/tests/prompts/harness.cjs @@ -0,0 +1,51 @@ +const fs = require('node:fs'); +const vm = require('node:vm'); +const path = require('node:path'); +const root = path.resolve(__dirname, '../../components/ts_webui/web'); +const read = file => fs.readFileSync(path.join(root,file),'utf8'); +class Element { + constructor(tag, doc) { this.tagName=tag.toUpperCase();this.doc=doc;this.children=[];this.style={};this.dataset={};this.attributes={};this.className='';this.textContent='';this.value='';this.disabled=false;this.hidden=false; + this.classList={add:(...ns)=>{this.className=[...new Set([...this.className.split(' '),...ns])].join(' ').trim();},remove:(...ns)=>{this.className=this.className.split(' ').filter(n=>!ns.includes(n)).join(' ');},contains:n=>this.className.split(' ').includes(n),toggle:(n,on)=>on?this.classList.add(n):this.classList.remove(n)}; + } + set id(v){this._id=v;this.doc.elements.set(v,this);} get id(){return this._id;} + setAttribute(k,v){this.attributes[k]=v;if(k.startsWith('data-'))this.dataset[k.slice(5).replace(/-([a-z])/g,(_,c)=>c.toUpperCase())]=v;} + getAttribute(k){return this.attributes[k];} hasAttribute(k){return k in this.attributes;} + appendChild(n){n.parent=this;this.children.push(n);return n;} append(...ns){ns.forEach(n=>this.appendChild(n));} + replaceChildren(...ns){this.children=[];this.append(...ns);this.textContent='';} + remove(){if(this.parent)this.parent.children=this.parent.children.filter(n=>n!==this);if(this.id)this.doc.elements.delete(this.id);} + removeChild(n){n.remove();} querySelectorAll(s){return this.children.filter(n=>s==='*'||s.startsWith('.')&&n.classList.contains(s.slice(1)));} + querySelector(s){return this.querySelectorAll(s)[0]||null;} + click(){this.onclick?.();} focus(){} scrollIntoView(){} +} +function harness(language='zh-CN') { + const listeners={}, elements=new Map(), timers=new Map();let now=0,id=0; + const doc={elements,documentElement:{},visibilityState:'visible',addEventListener(){},removeEventListener(){}, + createElement:tag=>new Element(tag,doc),getElementById:id=>elements.get(id)||null, + querySelectorAll:()=>[],querySelector:s=>s==='main'?doc.main:null}; + doc.body=new Element('body',doc);doc.head=new Element('head',doc);doc.main=new Element('main',doc); + const el=(id,tag='div')=>{let n=elements.get(id);if(!n){n=doc.createElement(tag);n.id=id;doc.body.appendChild(n);}return n;}; + ['app','lang-name','lang-menu','ws-status','page-content'].forEach(id=>el(id)); + const storage=new Map([['ts_language',language]]); + const logs=[]; + const context={document:doc,navigator:{language},localStorage:{getItem:k=>storage.get(k)||null,setItem:(k,v)=>storage.set(k,String(v)),removeItem:k=>storage.delete(k)}, + console:{log(){},debug(){},warn:(...x)=>logs.push(x),error:(...x)=>logs.push(x)}, + setTimeout:(fn,ms=0)=>{timers.set(++id,{fn,at:now+ms});return id;},clearTimeout:n=>timers.delete(n), + setInterval:(fn,ms)=>{timers.set(++id,{fn,at:now+ms,repeat:ms});return id;},clearInterval:n=>timers.delete(n), + Date:class extends Date{static now(){return now;}},CustomEvent:class{constructor(type,init={}){this.type=type;this.detail=init.detail;}}, + JSON,AbortController,URL,URLSearchParams,Blob,TextDecoder,TextEncoder,Map,Set,Promise,Error,SyntaxError, + location:{host:'127.0.0.1',protocol:'http:',hash:''},CSS:{escape:s=>s}, + addEventListener:(k,f)=>(listeners[k]??=[]).push(f),removeEventListener(){}, + dispatchEvent:event=>(listeners[event.type]||[]).forEach(f=>f(event)), + confirm:()=>true,prompt:()=>null,WebSocket:class{static OPEN=1;static CONNECTING=0;}, + fetch:async()=>{throw new Error('Network must be explicitly mocked');}}; + context.window=context;const ctx=vm.createContext(context); + const run=code=>vm.runInContext(code,ctx); + run(read('index.html').match(/