杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • 仓库概览
    • 运行环境与 SDK 集成
    • 工程结构与目录导航
  • 核心 SDK 架构

    • SDK 库体系与模块划分
    • 蓝牙连接与 RCSP 协议
    • 广播包解析与设备认证
    • 日志助手与调试支持
  • 设备功能模块

    • OTA 固件升级
    • 表盘管理与自定义表盘
    • 图像转换工具
    • 资源打包
    • 音频编解码
    • 健康与运动数据同步
    • 消息通知与实用设备功能
  • 宜动健康示例应用

    • 应用架构与页面导航
    • 健康界面与数据可视化
    • 设备连接与数据同步
    • 登录注册与用户中心
    • AI 云服务与语音交互
    • 本地数据库与持久化
    • 多语言国际化
  • 测试与调试

    • SDKTestHelper 功能测试工具
    • 音频编解码示例工程
    • 调试技巧与问题排查
  • 文档与资源

    • 在线文档与版本历史
    • 第三方框架与依赖管理

OTA 固件升级

杰理健康(iOS-JL_Health)App 中设备固件无线升级(OTA)的编排层实现。App 通过 JL_RunSDK 单例封装访问杰理官方蓝牙 SDK(JL_BLEKit.framework),以 UUID 状态机、全局通知和升级标志位驱动耳机的固件升级全流程。

Purpose and Scope

本页聚焦 iOS-JL_Health 中 OTA 固件升级相关的应用层编排机制,包括:

  • JL_RunSDK 对蓝牙/OTA 能力的统一封装与全局宏
  • 设备 UUID 的 OTA 状态机(JLUuidType)
  • OTA 相关的全局通知(kUI_JL_DEVICE_OTA、kUI_OTA_IS_OK 等)
  • 升级中/失败重连的标志位管理
  • 4G 模块升级(JLPublic4GModel)的扩展入口

明确不在本页范围:OTA 底层传输协议、分包策略、固件校验与烧录流程由 JL_BLEKit.framework 二进制 SDK 实现(该 SDK 头文件未包含在本仓库源码中,仅以 framework 形式引入),本页只覆盖仓库内可验证的 App 侧编排代码。表盘升级(JLDialUnit)、AI 语音(AIKIT)等能力各有独立页面,本页不做展开。

Overview

iOS-JL_Health 是杰理科技(www.zh-jieli.com)推出的健康类 App,通过 BLE 连接杰理芯片的耳机/音箱等设备。OTA(Over-The-Air)固件升级是该类设备的核心能力之一:用户无需线材,即可通过手机蓝牙将新固件写入设备。

在仓库中,OTA 的完整链路是:

App UI/业务层 → JL_RunSDK(应用封装)→ JL_BLEMultiple / JL_EntityM(连接管理)
              → JL_BLEKit(SDK:CmdManager / OTAManager)→ BLE 设备

JL_RunSDK.h 位于 code/JL_Health/JieliJianKang/JL_RunSDK.h,是整个应用与 SDK 交互的唯一门面。它暴露了:

  • 全局快捷宏 kJL_BLE_Multiple、kJL_BLE_EntityM、kJL_BLE_CmdManager、kJL_BLE_Uuid,业务代码通过这些宏快速取得当前连接、命令管理器与设备 UUID;
  • 设备连接/切换 API(connectDevice:、setActiveUUID:、getEntity:);
  • 设备状态查询 API(getStatusUUID:),其中状态 3 即"UUID 需要 OTA";
  • 两个 OTA 运行时标志:isOtaUpgrading(是否正在升级)与 isOTAFailRelink(升级失败后是否重连);
  • 4G 模块升级模型 g4Model。

设计意图:将 SDK 的复杂度收敛在单例之后。业务页面(如设备设置、升级弹窗)只依赖 JL_RunSDK 的宏、通知和标志位,不必感知 SDK 内部的对象生命周期,从而降低多设备、多 UUID 场景下的出错概率。

Architecture

flowchart TD
    subgraph sg_App["App 业务层 (JieliJianKang)"]
        UI["设备页面 / 升级弹窗"]
        Notif["全局通知<br/>kUI_JL_DEVICE_OTA / kUI_OTA_IS_OK"]
        Flags["isOtaUpgrading / isOTAFailRelink"]
    end

    subgraph sg_RunSDK["封装层 JL_RunSDK (单例)"]
        RSDK["JL_RunSDK sharedMe"]
        MACRO["宏: kJL_BLE_Multiple<br/>kJL_BLE_EntityM<br/>kJL_BLE_CmdManager"]
        UUIDSTATE["getStatusUUID: → JLUuidType"]
        CONNECT["connectDevice: / setActiveUUID:"]
        G4["g4Model (4G 模块升级)"]
    end

    subgraph sg_SDK["SDK 层 (JL_BLEKit.framework)"]
        BLEM["JL_BLEMultiple"]
        ENTITY["JL_EntityM<br/>mCmdManager"]
        CMD["命令管理器 (OTA 命令下发)"]
        OTA["OTAManager<br/>(固件传输/烧录)"]
    end

    subgraph sg_Device["设备"]
        DEV["BLE 设备 (杰理芯片)"]
    end

    UI -->|"读取状态/发起升级"| RSDK
    RSDK --> MACRO
    RSDK --> UUIDSTATE
    RSDK --> CONNECT
    RSDK --> G4
    MACRO -->|"访问"| BLEM
    MACRO -->|"访问"| ENTITY
    CONNECT --> ENTITY
    ENTITY --> CMD
    CMD --> OTA
    OTA -->|"BLE 传输固件"| DEV
    DEV -->|"升级结果回调"| Notif
    Notif --> Flags
    Flags --> UI

架构说明:

  1. 业务层只与 JL_RunSDK 交互。UI 通过宏取得命令管理器后,可向 SDK 下发 OTA 相关指令(具体指令集由 JL_BLEKit 提供)。
  2. JL_RunSDK 单例是全局状态的中枢:持有 mBleMultiple(多连接控制中心)、mBleEntityM(当前设备实体)、mBleUUID(当前 UUID)、isOtaUpgrading 等。
  3. SDK 层(JL_BLEKit.framework)负责真实的 BLE 连接、OTA 协议与烧录。其内部实现(JL_OTAManager 等)为二进制发布,本仓库不含其源码,故图中以虚线边界标识。
  4. 设备升级结果通过全局通知回流到 App 层,更新标志位并驱动 UI 刷新——这是典型的"SDK 回调 → 通知 → UI"单向数据流,避免 UI 直接持有 SDK 强引用。

核心机制详解

JL_RunSDK 单例与全局宏

JL_RunSDK 以 sharedMe 提供单例,头文件中定义了四个高频宏,把"当前设备/当前命令管理器"从对象图中提取为全局符号:

#define kJL_BLE_Multiple    [[JL_RunSDK sharedMe] mBleMultiple]     //蓝牙控制中心
#define kJL_BLE_EntityM     [[JL_RunSDK sharedMe] mBleEntityM]      //当前蓝牙设备
#define kJL_BLE_CmdManager  kJL_BLE_EntityM.mCmdManager             //命令管理器
#define kJL_BLE_Uuid        [[JL_RunSDK sharedMe] mBleUUID]         //当前蓝牙设备的UUID

Source: JL_RunSDK.h

设计意图:宏替代方法调用。kJL_BLE_CmdManager 经由 kJL_BLE_EntityM 链式取值,保证命令管理器始终来自"当前正在使用的设备实体",在多设备场景下天然避免串设备;同时宏在编译期展开、无运行时开销。

UUID 状态机:JLUuidType

JLUuidType 枚举描述了每个已扫描/已连接 UUID 的生命周期状态,其中 JLUuidTypeNeedOTA = 3 是 OTA 的关键状态:

typedef NS_ENUM(UInt8, JLUuidType) {
    JLUuidTypeDisconnected              = 0,    //未连接的UUID
    JLUuidTypeConnected                 = 1,    //已连接的UUID
    JLUuidTypeInUse                     = 2,    //正在使用的UUID
    JLUuidTypeNeedOTA                   = 3,    //UUID需要OTA
    JLUuidTypePreparing                 = 4,    //正在准备的UUID
};

Source: JL_RunSDK.h

状态语义与流转:

状态值含义触发场景
JLUuidTypeDisconnected0未连接扫描到但未建立连接
JLUuidTypeConnected1已连接BLE 链路已建立
JLUuidTypeInUse2正在使用已切换为当前操作设备
JLUuidTypeNeedOTA3需要 OTA设备固件版本过低或进入升级模式,SDK 要求先升级
JLUuidTypePreparing4正在准备设备正在初始化/进入可操作状态

JLUuidTypeNeedOTA 的设计意图:当设备固件与 App 协议不兼容时,SDK 会将设备置为"需要 OTA"状态,App 检测到该状态后应优先引导用户升级固件,而不是继续尝试普通功能——这从机制上保证了"旧固件设备不会被错误操作"。

状态查询接口 getStatusUUID: 的文档注释明确列出了这 5 种取值(见头文件第 128-136 行),业务层据此决定是否弹出升级引导。

OTA 全局通知

JL_RunSDK.h 声明了两个与 OTA 直接相关的通知名,以及一组设备变更通知:

extern NSString *kUI_JL_DEVICE_CHANGE;
extern NSString *kUI_JL_DEVICE_PREPARING;
extern NSString *kUI_JL_DEVICE_OTA;
extern NSString *kUI_RECONNECT_TO_DEVICE;
extern NSString *kUI_OTA_IS_OK;

Source: JL_RunSDK.h

  • kUI_JL_DEVICE_OTA:设备进入 OTA 流程(或 OTA 状态变化)时发出,UI 据此显示升级进度界面。
  • kUI_OTA_IS_OK:OTA 成功完成时发出,UI 据此关闭升级界面、刷新设备信息。
  • kUI_JL_DEVICE_PREPARING:设备处于"正在准备"状态时发出,与 JLUuidTypePreparing 对应。
  • kUI_RECONNECT_TO_DEVICE:升级完成后引导重连设备时发出(常与 isOTAFailRelink 配合)。

这些通知由 SDK 回调在 JL_RunSDK 内部转发(转发逻辑位于 .m 实现中,未包含在头文件),业务页面通过 NSNotificationCenter 监听,实现了解耦。

升级标志位:isOtaUpgrading 与 isOTAFailRelink

@property(assign,nonatomic)BOOL           isOtaUpgrading;
@property(assign,nonatomic)BOOL           isOTAFailRelink;

Source: JL_RunSDK.h

  • isOtaUpgrading = YES:表示当前正在执行 OTA。业务层可用它做互斥保护——升级期间禁止发起其他会占用 BLE 链路的操作(如音乐播放、表盘传输),避免命令冲突。
  • isOTAFailRelink = YES:表示上一次 OTA 失败,App 需要重新连接设备以恢复。该标志位让业务层区分"正常连接"与"升级失败后的恢复连接",后者通常需要更长的超时容忍和重试提示。

这两个标志位与通知配合,构成了 OTA 的"状态-事件"双通道:标志位适合同步判断(如按钮点击时检查),通知适合异步响应(如升级结束刷新 UI)。

4G 模块升级入口

///4G 模块升级
@property(strong,nonatomic)JLPublic4GModel *g4Model;
@property(assign,nonatomic)int g4ModelVendor;

Source: JL_RunSDK.h

除经典蓝牙耳机外,JL_RunSDK 还预留了 4G 模块升级通道:g4Model 承载 4G 模块的升级数据模型,g4ModelVendor 标识模块厂商。这说明 OTA 能力被设计为可扩展的——不同传输介质(BLE / 4G)共用同一套"模型 + 状态 + 通知"框架,业务层无需感知底层介质差异。

核心流程:OTA 升级端到端时序

以下时序图基于仓库可验证的 API(JL_RunSDK 的连接/状态/通知机制)绘制,SDK 内部步骤(OTAManager 传输)以虚线标注,表示由 JL_BLEKit.framework 二进制实现:

sequenceDiagram
    participant UI as 业务页面
    participant R as JL_RunSDK (sharedMe)
    participant S as JL_BLEKit SDK
    participant D as BLE 设备

    UI->>R: getStatusUUID: → JLUuidTypeNeedOTA(3)
    R-->>UI: 状态=3(需要 OTA)
    UI->>UI: 展示升级引导弹窗
    UI->>R: 设置 isOtaUpgrading = YES
    UI->>R: 通过 kJL_BLE_CmdManager 下发 OTA 指令
    R->>S: mCmdManager → OTAManager 启动升级
    S->>D: BLE 传输固件分包
    D-->>S: 进度/校验反馈
    S-->>R: 升级结果回调
    R-->>UI: 通知 kUI_OTA_IS_OK
    R->>R: isOtaUpgrading = NO
    UI->>R: 通知 kUI_RECONNECT_TO_DEVICE 引导重连
    alt 升级失败
        S-->>R: 失败回调
        R->>R: isOTAFailRelink = YES
        R-->>UI: 通知 kUI_JL_DEVICE_OTA(失败态)
        UI->>R: connectDevice: 重新连接
    end

流程要点:

  1. 状态探测:页面通过 getStatusUUID: 判断设备是否处于 JLUuidTypeNeedOTA,这是升级流程的入口条件;
  2. 互斥保护:升级开始前将 isOtaUpgrading 置位,阻断其他 BLE 业务;
  3. 命令下发:业务层通过 kJL_BLE_CmdManager(即 kJL_BLE_EntityM.mCmdManager)向 SDK 的 OTA 管理器发送升级指令,保证指令绑定"当前使用中的设备";
  4. 结果回流:SDK 以通知形式(kUI_OTA_IS_OK / kUI_JL_DEVICE_OTA)把结果交还 UI,同时更新标志位;
  5. 失败恢复:失败后 isOTAFailRelink 置位,UI 走 connectDevice: 重连路径,而不是普通连接路径。

Usage Examples

示例 1:查询设备是否需要 OTA

业务层判断设备 UUID 状态、决定是否弹出升级引导的典型模式:

/**
  获取当前设备状态
        0:未连接的UUID
        1:已连接的UUID
        2:正在使用的UUID
        3:UUID需要OTA
        4:正在准备的UUID
*/
+(JLUuidType)getStatusUUID:(NSString*)uuid;

Source: JL_RunSDK.h

调用方式(示意,由头文件签名推导):

JLUuidType type = [JL_RunSDK getStatusUUID:kJL_BLE_Uuid];
if (type == JLUuidTypeNeedOTA) {
    // 弹出升级引导,进入 OTA 流程
}

示例 2:升级期间互斥与失败重连标志

升级状态标志位用于业务互斥与失败恢复判定:

@property(assign,nonatomic)BOOL           isOtaUpgrading;
@property(assign,nonatomic)BOOL           isOTAFailRelink;

Source: JL_RunSDK.h

典型用法:升级完成后 UI 监听 kUI_OTA_IS_OK 通知并复位 isOtaUpgrading;若 isOTAFailRelink == YES,则调用 connectDevice: 走恢复连接流程:

-(void)connectDevice:(JL_EntityM*)entityM callBack:(void (^)(BOOL))callBack;

Source: JL_RunSDK.h

示例 3:4G 模块升级模型扩展

对 4G 形态设备,直接通过 JL_RunSDK 的公开属性装载升级模型:

///4G 模块升级
@property(strong,nonatomic)JLPublic4GModel *g4Model;
@property(assign,nonatomic)int g4ModelVendor;

Source: JL_RunSDK.h

业务层可复用同一套升级编排逻辑,仅切换数据模型与厂商标识(g4ModelVendor),体现 OTA 框架的介质无关性。

配置选项

OTA 编排层本身的配置集中在 JL_RunSDK.h 顶部的编译期宏与全局常量中。以下配置与 OTA 链路(服务器下发固件信息、SDK 鉴权)间接相关:

配置项类型默认值说明
BaseURL宏 (NSString)@"http://health.jieliapp.com"杰理服务器地址,用于固件/表盘等资源下发;注释标注测试域名 test03.jieliapp.com
APPID_VALUE宏 (NSString)@"94df387f"SDK 应用标识,OTA 鉴权/统计使用
APIKEY宏 (NSString)@"65dbf2af3c95900e31024e6d2e3b99da"SDK 接口密钥
APISERECT宏 (NSString)Base64 字符串SDK 接口密钥密文
isOtaUpgrading属性 (BOOL)NO运行时标志:是否正在 OTA 升级
isOTAFailRelink属性 (BOOL)NO运行时标志:OTA 失败后是否处于重连恢复状态
g4ModelVendor属性 (int)04G 模块厂商标识,决定 4G 升级协议分支

Source: JL_RunSDK.h

注意:以上配置为 App 侧可见项;JL_BLEKit SDK 内部的 OTA 传输参数(分包大小、超时、重试次数等)由框架二进制内置,仓库源码中不可见。

API Reference

以下为 JL_RunSDK 中与 OTA 编排相关的公开接口(均来自 JL_RunSDK.h):

+(id)sharedMe

获取 JL_RunSDK 全局单例。所有 OTA 相关状态(isOtaUpgrading、isOTAFailRelink、g4Model)均挂载于此单例上。

Returns: JL_RunSDK 单例实例。

+(JLUuidType)getStatusUUID:(NSString*)uuid

查询指定 UUID 的设备状态,OTA 流程入口判断。

Parameters:

  • uuid (NSString*): 目标设备的蓝牙 UUID。

Returns: JLUuidType 枚举值:

  • JLUuidTypeDisconnected(0) — 未连接
  • JLUuidTypeConnected(1) — 已连接
  • JLUuidTypeInUse(2) — 正在使用
  • JLUuidTypeNeedOTA(3) — 需要 OTA
  • JLUuidTypePreparing(4) — 正在准备

+(JL_EntityM*)getEntity:(NSString*)uuid

通过 UUID 获取已连接的设备实体(JL_EntityM),其 mCmdManager 是 OTA 命令下发的载体。

-(void)connectDevice:(JL_EntityM*)entityM callBack:(void (^)(BOOL))callBack

连接指定设备实体,OTA 失败后恢复连接(isOTAFailRelink 场景)也走此接口。

Parameters:

  • entityM (JL_EntityM*): 目标设备实体。
  • callBack (void (^)(BOOL)): 连接结果回调,YES 表示成功。

+(void)setActiveUUID:(NSString*)uuid

切换当前使用的设备 UUID。多设备场景下,切换后 kJL_BLE_CmdManager 将指向新设备的命令管理器,确保 OTA 指令发往正确设备。

+(NSString*)textEntityStatus:(JL_EntityM_Status)status

将设备连接状态转换为中文描述,用于升级引导文案。

失败模式、边界情况与并发

OTA 失败与重连(isOTAFailRelink)

  • 现象:升级中断(蓝牙断开、固件校验失败、电量不足等)后,isOTAFailRelink 被置为 YES。
  • 处理:业务层应避免直接进入普通功能流程,而是调用 connectDevice: 重建链路;通知 kUI_JL_DEVICE_OTA 以失败态通知 UI,引导用户重试。
  • 设计意图:将"失败恢复"显式建模为独立状态,防止恢复连接被误判为首次连接而跳过必要的固件恢复动作。

升级期间并发操作冲突

  • isOtaUpgrading 提供互斥信号。升级进行中,业务层应禁止音乐播放、表盘传输、EQ 调整等其他 BLE 命令。
  • 原因:BLE 链路同一时刻承载一个主要事务,OTA 分包传输占用带宽且对时序敏感,混入其他命令可能破坏固件包顺序。

多设备/多 UUID 场景

  • JLUuidType 按 UUID 独立维护状态,kJL_BLE_CmdManager 始终解析自"当前使用设备",避免命令串设备。
  • 边界情况:若用户切换设备(setActiveUUID:)发生在升级中途,isOtaUpgrading 仍是全局标志——业务层应在切换前检查该标志,阻止切换或在切换后终止升级。

蓝牙关闭(JLUuidTypeDisconnected / JLDeviceChangeTypeBleOFF)

  • 蓝牙被系统关闭时,所有 UUID 回落为未连接状态,进行中的 OTA 必然失败;isOTAFailRelink 与 kUI_JL_DEVICE_CHANGE(值 4) 通知配合,UI 可提示"蓝牙已关闭,升级中断"。

固件版本过低的设备

  • 设备固件与 App 协议不兼容时,SDK 将设备置为 JLUuidTypeNeedOTA(3)。此时普通功能不可用是预期行为,App 应优先引导升级,而非反复尝试连接失败。

性能与运维注意

  • 升级耗时由固件大小与 BLE 吞吐决定,App 侧应通过 isOtaUpgrading 阻断并发命令,并在 UI 上显示进度(进度回调由 SDK 通知驱动)。
  • 电量/链路稳定性:BLE OTA 对链路稳定性敏感,建议升级前检查设备电量与信号强度;失败后依赖 isOTAFailRelink + connectDevice: 自动恢复路径。
  • 服务器配置:BaseURL 区分测试(test03.jieliapp.com)与上架(health.jieliapp.com)环境,升级固件资源下发依赖该域名,发版前需确认指向正式环境。

扩展点

  1. 新设备形态(4G):通过 g4Model + g4ModelVendor 扩展,复用既有状态机与通知框架,无需改动 UI 编排逻辑。
  2. 新升级策略:业务层可在 kUI_OTA_IS_OK 通知回调处扩展"升级后动作"(如恢复用户配置、重新鉴权),通知机制保证了回调点的统一性。
  3. SDK 能力替换:JL_RunSDK 门面封装了 JL_BLEKit 的引用(#import <JL_BLEKit/JL_BLEKit.h>),若未来更换 SDK 版本或厂商,仅需调整 .m 实现中的桥接,头文件对外契约(宏、通知、标志位)可保持不变。

相关链接

  • JL_RunSDK.h — OTA 编排层头文件
  • JL_RunSDK.h — UUID 状态机定义(L41-L47)
  • JL_RunSDK.h — OTA 通知常量(L56-L68)
  • JL_RunSDK.h — 升级标志位(L89-L90)
  • JL_RunSDK.h — 4G 模块升级模型(L98-L100)

说明:OTA 底层协议实现位于 JL_BLEKit.framework(杰理官方 SDK,二进制发布),仓库中不包含其源码;本文档所有结论均来自仓库内可验证的 JL_RunSDK.h 及项目结构。

测试与验证

仓库证据说明:在本仓库源码(code/JL_Health/JieliJianKang/)中未检索到针对 OTA 编排层的独立单元测试或 UI 测试用例(OTA、Upgrade 等关键词在 Swift/ObjC 源码中无命中)。这符合该项目的工程形态:OTA 核心逻辑位于 JL_BLEKit.framework 二进制 SDK 内,App 侧仅做薄封装,测试重点落在 SDK 自身与真机联调。

建议的验证清单(基于本页文档的机制推导,供集成时参考):

场景验证点预期
固件版本过低设备getStatusUUID: 返回值JLUuidTypeNeedOTA(3),UI 弹出升级引导
正常升级isOtaUpgrading 标志 + 通知升级期间为 YES,收到 kUI_OTA_IS_OK 后复位
升级中蓝牙断开isOTAFailRelink 标志置为 YES,connectDevice: 恢复连接
升级中断开重连后状态查询设备恢复正常状态(非 NeedOTA)或重新进入升级
多设备并发kJL_BLE_CmdManager 指向OTA 指令始终发往当前使用设备

总结

OTA 固件升级在 iOS-JL_Health 中的实现遵循**"薄封装 + 强契约"**架构:JL_RunSDK 单例对外暴露稳定的宏、状态枚举、通知与标志位,内部桥接 JL_BLEKit SDK。升级流程由四个机制协同驱动:

  1. 状态机(JLUuidType)判定设备是否需要 OTA;
  2. 标志位(isOtaUpgrading / isOTAFailRelink)提供互斥与失败恢复语义;
  3. 通知(kUI_JL_DEVICE_OTA / kUI_OTA_IS_OK)将 SDK 回调异步回流 UI;
  4. 命令管理器宏(kJL_BLE_CmdManager)保证指令精确绑定当前设备。

这种设计让业务页面无需感知 SDK 内部复杂度,同时为 4G 模块等新形态预留了扩展入口,是设备类 App 集成厂商 SDK 时的典型范式。

Next
表盘管理与自定义表盘