["w9"]="1.3.107"
["lt22"]="1.3.107"
["n9"]="1.3.113"
- ["ln"]="1.1.46"
+ ["ln"]="1.0.47"
["lnppp"]="1.1.1"
["n9ln"]="1.0.0"
/* 4G/Cat1 模组升级:与文件下载成功/失败同一套成功页(无重启提示),可按键返回 */
if (GetOtaStatus() == OTA_UI_STATUS_CAT1_START) {
if (status == 3) {
+ ln_cat1_ota_set_last_failed(1);
if (OtaView::GetInstance()) {
OtaView::GetInstance()->ChangeView(OtaView::OTA_VIEW_UPDATING, OtaView::OTA_VIEW_UPDATE_SUCCESS);
}
uint8_t min = 0;
const bool still_1047 = (uapi_get_fw_version(&maj, &mid, &min) == ERRCODE_SUCC && maj == 1 && mid == 0 &&
min == 47);
- const bool py34_prereq = ln_cat1_py34_prereq_met();
- if (still_1047 && !py34_prereq) {
- char kv_mark[8] = {0};
- (void)UtilsGetValue("cat1_py34_upgrade_done", kv_mark, sizeof(kv_mark));
+ /* Cat1 会话成功但 modem+py 未达蓝牙准入:继续 Cat1,不进入手表升级 */
+ if (still_1047 && !ln_cat1_may_proceed_to_watch_ota()) {
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
- "[ota]CheckOtaResult: Cat1 round done but py34 prereq not met, py=%u kv=%s verified=%d, stay updating",
- (unsigned)uapi_get_py_ver(), kv_mark, uapi_cat1_ota_is_py34_verified());
+ "[ota]CheckOtaResult: Cat1 ok but profile not ready for watch OTA, py=%u profile=%d",
+ (unsigned)uapi_get_py_ver(), ln_cat1_already_at_v34_source_profile());
SetOtaStatus(OTA_UI_STATUS_CAT1_START);
ThunderBirdModel::GetInstance()->PrepareCat1NextRoundAfterSuccess();
if (OtaUpdatingView::GetInstance()) {
OtaSuccessView::GetInstance()->UpdateDownloadSuccess("模组升级成功");
}
#ifdef SUPPORT_CAT1_SERVICE
- /* 本次 Cat1 真升:URL 目标 V34 + 当前 py>=34 + OTA 前基线 < 34 */
- if (status == 4 && ln_cat1_last_package_urls_target_py() == 34 && uapi_get_py_ver() >= 34 &&
- uapi_cat1_ota_get_py_baseline() < 34) {
+ if (ln_cat1_already_at_v34_source_profile()) {
(void)UtilsSetValue("cat1_py34_upgrade_done", "1");
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
- "[ota]CheckOtaResult: Cat1 verified py34, baseline=%u->%u, KV cat1_py34_upgrade_done=1",
- (unsigned)uapi_cat1_ota_get_py_baseline(), (unsigned)uapi_get_py_ver());
}
+ ln_cat1_ota_set_last_failed(0);
#endif
}
SetOtaStatus(OTA_UI_STATUS_NOT_START);
/*************************OTA升级*************************/
int ThunderBirdModel::ota_update_boot()
{
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, nullptr, 0);//获取是否需要OTA升级
+ if (ln_cat1_may_proceed_to_watch_ota()) {
+ ln_ota_request_watch_ota_detection("ota_update_boot");
+ } else {
+ do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_IS_CAT1_OTA_UPGRADE, nullptr, 0);
+ }
return -1;
}
if(cat1_model_oat_suc_flag == 1) //验证cat1模组有没有升级成功,如果收到消息,说明升级成功
{
cat1_model_oat_suc_flag = 0;//升级成功后,将标志位设为0
- printf("模组升级成功\n");
- push_ota_status(OTA_UI_STATUS_SUCCESS);
+ if (ln_cat1_ota_timer_check_success()) {
+ printf("模组升级成功(profile/py ok)\n");
+ ln_cat1_ota_set_last_failed(0);
+ push_ota_status(OTA_UI_STATUS_SUCCESS);
+ } else {
+ printf("模组UDP成功消息但 profile/py 未达标,继续等待\r\n");
+ }
// LOS_Msleep(1000);
/* 不在 4G 模组 OTA 成功后立即重启,便于继续走后续手表 OTA(原 shutdown_reboot_prejobs(2)) */
printf("[OTA] Cat1 modem OTA success: skip immediate reboot, continue host OTA flow\r\n");
printf("modem_ota_timer_CallBack %d old_model_ver %d g_py_ver %d baseline %u\n", mode_ota_count,
old_model_ver, uapi_get_py_ver(), (unsigned)uapi_cat1_ota_get_py_baseline());
#ifdef BOARD_LEINIAO
- {
- uint8_t cur_py = uapi_get_py_ver();
- uint8_t target_py = cat1_ota_resolve_target_py();
- uint8_t baseline_py = uapi_cat1_ota_get_py_baseline();
- cat1_ota_ok = (cur_py >= target_py && cur_py > baseline_py) ? 1 : 0;
- }
+ cat1_ota_ok = ln_cat1_ota_timer_check_success();
#else
cat1_ota_ok = (old_model_ver != uapi_get_py_ver()) ? 1 : 0;
#endif
uint8_t TRANSMIT_DATA=TRANS_FREE;
#ifdef BOARD_LEINIAO
+ ln_cat1_ota_set_last_failed(0);
uapi_cat1_ota_mark_py34_verified();
push_ota_status(OTA_UI_STATUS_SUCCESS);
/* 不在 4G 模组 OTA 成功后立即重启,便于继续后续手表 OTA(原 shutdown_reboot_prejobs(REBOOT_TYPE)) */
- printf("[OTA] Cat1 OTA ok: cur>baseline and >= target, skip immediate reboot\r\n");
+ printf("[OTA] Cat1 OTA ok: profile or py progress, skip immediate reboot\r\n");
#else
CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1);
#endif
} else {
mode_ota_count++;
- if(mode_ota_count>120 || g_py_ver_new==0)
+ /* 仅超时判失败;BOOTUP 清 g_py_ver_new 不再误触发失败 */
+ if (mode_ota_count > 120)
{
uint8_t TRANSMIT_DATA=OTA_UPDATA_FAIL;
CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1);
#ifdef BOARD_LEINIAO
+ ln_cat1_ota_set_last_failed(1);
push_ota_status(OTA_UI_STATUS_FAILED);
- printf("[OTA] Cat1 OTA timeout/fail py=%u baseline=%u target=%u\r\n",
+ printf("[OTA] Cat1 OTA timeout fail py=%u baseline=%u target=%u profile=%d\r\n",
(unsigned)uapi_get_py_ver(), (unsigned)uapi_cat1_ota_get_py_baseline(),
- (unsigned)cat1_ota_resolve_target_py());
+ (unsigned)cat1_ota_resolve_target_py(), ln_cat1_already_at_v34_source_profile());
#endif
if(modem_ota_timer){
CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1);
#endif
+ ln_cat1_ota_set_last_failed(0);
uapi_cat1_ota_begin(ver);
old_model_ver=ver;
/* ============================== 公共宏与URL路径 ============================== */
#define LN_VOICE_CHAT_ENABLED 0 //声纹锁开启宏
-#define LN_ENV_PRODUCTION 1 //正式环境
+#define LN_ENV_PRODUCTION 0 //正式环境
/* 接口基础配置 - 如需切换环境/密钥,在此调整 */
#if LN_ENV_PRODUCTION
#define LN_BASE_URL "https://ambybox-o.api.leiniao.com/ambybox-device-api" //正式环境服务器地址
const char *device_token,
const char *source_version);
+/* 与 ln_api_interface.h 中声明一致,供 C 模块包含 ln_api.h 时使用 */
+int ln_ota_version_string_is_1047(const char *version);
+void ln_ota_request_watch_ota_detection(const char *reason);
+
uint32_t ln_ota_download_flow_http(const char *device_id,
const char *device_token,
const char *source_version);
}
/* 目标版本为 1.0.47(可带 V 前缀、日期后缀如 1.0.47_20260427) */
-static int ln_ota_target_is_1047(const char *target)
+int ln_ota_version_string_is_1047(const char *target)
{
if (!target || target[0] == '\0') {
return 0;
return 0;
}
-/* 1.0.47 手表 OTA:须满足 Py34 前置(KV 或本次 Cat1 会话真升),不能仅口播已是 V34 */
-static int ln_ota_reject_1047_if_not_py34(const char *target)
+/* 是否处于 1.0.47 升级链路(当前手表版本或目标版本为 1.0.47) */
+static int ln_ota_on_1047_upgrade_track(const char *target_ver)
{
- return ln_ota_target_is_1047(target) && !ln_cat1_py34_prereq_met();
+ uint8_t major = 0;
+ uint8_t mid = 0;
+ uint8_t minor = 0;
+
+ if (uapi_get_fw_version(&major, &mid, &minor) == ERRCODE_SUCC &&
+ major == 1 && mid == 0 && minor == 47) {
+ return 1;
+ }
+ if (target_ver && ln_ota_version_string_is_1047(target_ver)) {
+ return 1;
+ }
+ return 0;
+}
+
+/** Cat1 未达标时禁止手表/蓝牙 OTA(仅 1.0.47 链路生效) */
+static int ln_ota_cat1_blocks_watch_ota(const char *target_ver)
+{
+ if (!ln_ota_on_1047_upgrade_track(target_ver)) {
+ return 0;
+ }
+ return !ln_cat1_may_proceed_to_watch_ota();
}
/* 无 4G 升级包且 Py34 未达标:提示用户联系售后 */
static void ln_ota_notify_py34_unqualified_no_firmware(void)
{
- if (ln_cat1_py34_prereq_met()) {
+ if (ln_cat1_may_proceed_to_watch_ota()) {
return;
}
- if (!ln_ota_target_is_1047(uapi_ln_get_device_version())) {
+ if (!ln_ota_on_1047_upgrade_track(NULL)) {
return;
}
push_ota_status(OTA_UI_STATUS_CAT1_PY34_FAIL);
}
+/** Cat1/modem+py 未达标时提示(仅 1.0.47 链路) */
+static void ln_ota_notify_watch_ota_blocked(void)
+{
+ if (ln_cat1_may_proceed_to_watch_ota() || !ln_ota_on_1047_upgrade_track(NULL)) {
+ return;
+ }
+ ln_ota_notify_py34_unqualified_no_firmware();
+}
+
+/** 唯一入口:modem 短串+py 达标后才发起手表/蓝牙 OTA getTask */
+void ln_ota_request_watch_ota_detection(const char *reason)
+{
+ if (ln_ota_cat1_blocks_watch_ota(NULL)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "[OTA] watch OTA blocked (%s): profile_ok=%d py=%u (need EG8AK0409+V34+1.0.47)",
+ reason ? reason : "",
+ ln_cat1_already_at_v34_source_profile(),
+ (unsigned)uapi_get_py_ver());
+ ln_ota_notify_watch_ota_blocked();
+ return;
+ }
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[OTA] watch OTA detection allowed (%s)", reason ? reason : "");
+ do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, NULL, 0);
+}
+
//解析 OTA 任务 JSON,决定是否触发下载
static void ln_handle_ota_task_response(const char *json_buf, int json_len)
{
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"解析OTA升级任务JSON");
- if (ln_ota_reject_1047_if_not_py34(uapi_ln_get_device_version()))
+ if (ln_ota_cat1_blocks_watch_ota(NULL))
{
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
- "[OTA] task rejected: 1.0.47 requires cat1 py34 (KV or verified session), py=%u kv=%d verified=%d",
- (unsigned int)uapi_get_py_ver(), ln_kv_cat1_py34_upgrade_done(), uapi_cat1_ota_is_py34_verified());
+ "[OTA] getTask response ignored: modem/py not qualified, profile=%d py=%u",
+ ln_cat1_already_at_v34_source_profile(),
+ (unsigned int)uapi_get_py_ver());
+ ln_ota_notify_watch_ota_blocked();
return;
}
} else {
push_upgrade_description_notification("");
}
+
+ if (ln_ota_cat1_blocks_watch_ota(targetVersion->valuestring)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "[OTA] getTask: cat1 not qualified, skip watch OTA UI (target=%s)",
+ targetVersion->valuestring);
+ ln_ota_notify_watch_ota_blocked();
+ cJSON_Delete(root);
+ free(text);
+ return;
+ }
if (ut == 0)
{
} else {
push_upgrade_description_notification("");
}
+
+ if (ln_ota_cat1_blocks_watch_ota(targetVersion->valuestring)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "[OTA] DeviceUpgrade blocked: cat1 not qualified (target=%s)",
+ targetVersion->valuestring);
+ ln_ws_send_device_upgrade_ack(
+ updateId->valuestring,
+ targetVersion->valuestring,
+ false,
+ "4G模组未达标,请先完成模组升级");
+ ln_ota_notify_watch_ota_blocked();
+ cJSON_Delete(root);
+ free(text);
+ return;
+ }
if (ut == 0)
{
if (!device_id || !device_token || !source_version)
return ERRCODE_FAIL;
+ if (ln_ota_cat1_blocks_watch_ota(source_version)) {
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+ "[OTA] ln_ota_get_task_http blocked: cat1 not qualified (source=%s)", source_version);
+ ln_ota_notify_watch_ota_blocked();
+ return ERRCODE_FAIL;
+ }
+
#ifdef SUPPORT_CAT1_SERVICE
/* CAT1 保活 */
cat1_api_add_cat1_app_vote();
printf("[OTA] ln_is_cat1_ota_upgrade_check: 开始检查CAT1 OTA升级\n");
#ifdef SUPPORT_CAT1_SERVICE
+ /* 蓝牙准入:modem 短串 + py 已达标则只查手表 OTA */
+ if (ln_cat1_may_proceed_to_watch_ota()) {
+ ln_ota_request_watch_ota_detection("modem+py profile ok");
+ return;
+ }
+
uint32_t ret = 0;
- // 直接获取CAT1 modem版本(如果版本还未获取,会在后续处理中处理)
char *text = cat1_api_runtime_get_cat1_modemver();
if (!text || strlen(text) == 0) {
- if (!ln_cat1_py34_prereq_met()) {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
- "[OTA] modem ver empty: py34 prereq not met, notify user");
- ln_ota_notify_py34_unqualified_no_firmware();
- return;
- }
- printf("[OTA] cat1 modem版本为空且py34已确认,执行普通OTA升级\n");
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, NULL, 0);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[OTA] modem ver empty, wait Cat1 (no watch OTA)");
+ ln_ota_notify_py34_unqualified_no_firmware();
return;
}
char version[16] = {0};
if (get_modem_fw_version_c(text, version) != 0) {
- if (!ln_cat1_py34_prereq_met()) {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
- "[OTA] modem ver parse fail: py34 prereq not met, notify user");
- ln_ota_notify_py34_unqualified_no_firmware();
- return;
- }
- printf("[OTA] 无法解析modem版本且py34已确认,执行普通OTA升级\n");
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, NULL, 0);
+ WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[OTA] modem ver parse fail, wait Cat1");
+ ln_ota_notify_py34_unqualified_no_firmware();
return;
}
// 检查cat1模组升级url是否为空
if(strlen(g_ln_last_package_url_new1) == 0 || strlen(g_ln_last_package_url_new2) == 0) {
- if (!ln_cat1_py34_prereq_met()) {
+ if (ln_cat1_may_proceed_to_watch_ota()) {
+ ln_ota_request_watch_ota_detection("cat1 url empty but profile ok");
+ } else {
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
- "[OTA] cat1 url empty: py34 prereq not met, notify user (py=%u kv=%d verified=%d)",
- (unsigned)uapi_get_py_ver(), ln_kv_cat1_py34_upgrade_done(), uapi_cat1_ota_is_py34_verified());
+ "[OTA] cat1 url empty and profile not ok (py=%u)", (unsigned)uapi_get_py_ver());
ln_ota_notify_py34_unqualified_no_firmware();
- return;
}
- printf("[OTA] cat1模组升级url为空且py34已确认,执行普通OTA升级\n");
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, NULL, 0);
} else {
printf("[OTA] cat1模组升级url不为空,触发CAT1升级\n");
+ ln_cat1_ota_set_last_failed(0);
push_ota_status(OTA_UI_STATUS_CAT1_START);
}
#else
- // 不支持CAT1服务,直接执行普通OTA升级
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_GET_TASK, NULL, 0);
+ ln_ota_request_watch_ota_detection("no cat1 service");
#endif
}
\ No newline at end of file
#include <cstring>
#include "kv_store.h"
#include "cat1_pub_api.h"
+#include "custom_utils.h"
#define LN_CAT1_PY34_MIN_VER 34
#define LN_KV_CAT1_PY34_UPGRADE_DONE "cat1_py34_upgrade_done"
int ln_cat1_py34_prereq_met(void)
{
- uint8_t py = uapi_get_py_ver();
- if (py < LN_CAT1_PY34_MIN_VER && py != 32) {
- return 0;
+ return ln_cat1_already_at_v34_source_profile();
+}
+
+static volatile int g_cat1_ota_last_failed = 0;
+
+void ln_cat1_ota_set_last_failed(int failed)
+{
+ g_cat1_ota_last_failed = failed ? 1 : 0;
+}
+
+int ln_cat1_ota_last_failed(void)
+{
+ return g_cat1_ota_last_failed;
+}
+
+int ln_cat1_may_proceed_to_watch_ota(void)
+{
+ uint8_t major = 0;
+ uint8_t mid = 0;
+ uint8_t minor = 0;
+
+ /* 非 1.0.47 手表软件:不做 Cat1 门禁 */
+ if (uapi_get_fw_version(&major, &mid, &minor) != ERRCODE_SUCC ||
+ major != 1 || mid != 0 || minor != 47) {
+ return 1;
}
+ return ln_cat1_already_at_v34_source_profile();
+}
+
+int ln_cat1_ota_timer_check_success(void)
+{
if (ln_cat1_already_at_v34_source_profile()) {
return 1;
}
- return ln_kv_cat1_py34_upgrade_done() || uapi_cat1_ota_is_py34_verified();
+ {
+ int target = ln_cat1_last_package_urls_target_py();
+ uint8_t target_py = 34;
+ uint8_t cur_py = uapi_get_py_ver();
+ uint8_t baseline_py = uapi_cat1_ota_get_py_baseline();
+
+ if (target > 0 && target <= 255) {
+ target_py = (uint8_t)target;
+ }
+ if (cur_py >= target_py && cur_py > baseline_py) {
+ return 1;
+ }
+ }
+ return 0;
}
// 推送文本给ui
int ln_cat1_last_package_urls_target_py(void);
/** KV cat1_py34_upgrade_done 是否为 1 */
int ln_kv_cat1_py34_upgrade_done(void);
-/** 本机已是 getTask 档位 47+EG8AK0409+V34(与 _1/_2 查询一致),无需 KV/verified */
+/**
+ * 蓝牙/手表 OTA 准入:实时 modem 短串(EG8AK0409) + py>=34 + 手表 1.0.47。
+ * 仅看当前版本,不看 KV / Cat1 会话成败。
+ */
int ln_cat1_already_at_v34_source_profile(void);
-/** Cat1 已真升到 Py34:已是 V34 档位、KV 或本次 OTA verified */
+/** 是否允许进入手表/蓝牙 OTA 检测(1.0.47 同 already_at_v34;其它手表版本不限制) */
+int ln_cat1_may_proceed_to_watch_ota(void);
+/** Cat1 OTA 定时器:是否判定本轮 Cat1 升级成功(先完整 profile,否则 py 相对基线提升) */
+int ln_cat1_ota_timer_check_success(void);
+/** 记录本轮 Cat1 UI 失败(仅 UI/日志,不阻挡蓝牙准入) */
+void ln_cat1_ota_set_last_failed(int failed);
+int ln_cat1_ota_last_failed(void);
+/** @deprecated 仅旧逻辑保留;蓝牙准入请用 ln_cat1_may_proceed_to_watch_ota */
int ln_cat1_py34_prereq_met(void);
+/** 版本字符串是否为 1.0.47(含 V 前缀、日期后缀) */
+int ln_ota_version_string_is_1047(const char *version);
+/**
+ * 唯一入口:在 Cat1 达标后才发起手表/蓝牙 OTA getTask 检测;未达标仅打日志/可选提示。
+ */
+void ln_ota_request_watch_ota_detection(const char *reason);
+
#ifdef __cplusplus
}
#endif