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

    • 项目概述与能力总览
    • 快速开始与 SDK 集成
  • SDK 核心接口

    • 发送接口 BleMethod
    • 接收接口 BleEventStream
    • 数据模型与常量定义
  • 平台原生实现

    • Android 原生层
    • iOS 原生层架构
    • iOS 蓝牙管理与 SDK 运行
    • 辅助连接与广播音箱
  • OTA 升级功能

    • 升级流程与传输通道
    • 自动回连机制
    • 复用空间升级
    • 自定义命令
  • 示例应用

    • 页面结构与用户旅程
    • 设备扫描与连接管理
    • 固件文件管理
    • 升级执行与状态展示
    • 设置与调试
  • 文档与支持

    • 接口文档与收发说明
    • 调试与问题排查

iOS 原生层架构

本文档描述 JL_OTA Flutter 插件的 iOS 原生实现层(code/JL_OTA/ios/Classes/),包括插件入口、BLE 管理核心、数据分包发送、协议处理、常量定义以及依赖的 DFUnits 工具框架,说明各模块如何协同完成 BLE 设备扫描、连接与 OTA 固件升级数据下发。

Purpose and Scope

本页聚焦于 JL_OTA 项目中 iOS 平台原生侧的架构与实现:

  • 覆盖内容:iOS 插件目录 code/JL_OTA/ios/Classes/ 下的模块划分(插件入口、BLE 管理、数据处理、广播协议、助手设备、广播音箱、常量定义),以及示例工程 code/JL_OTA/example/ios/ 中 DFUnits.framework 的依赖关系。
  • 不属于本页:Android 原生层实现(3-1-android-native)、Flutter/Dart 侧对外 API 设计、以及具体 OTA 升级协议字段细节,它们属于各自的目录页。

说明:本页依据仓库中实际文件布局编写。由于生成时源读取预算有限,各模块的职责描述以文件命名、目录结构及已确认的头文件清单为据;凡涉及推断处均已明确标注"推断",未验证的代码签名不会被虚构列出。

Overview

JL_OTA 是一个基于 Flutter 的杰理(Jieli)芯片 OTA 升级工具。与 Android 类似,iOS 侧通过 Flutter Platform Channel 与 Dart 层通信:Dart 调用 MethodChannel 发起命令,原生层通过 EventChannel 主动上报设备状态、升级进度与日志。

iOS 原生层的核心职责可概括为四点:

  1. BLE 设备管理:封装 CoreBluetooth 的扫描、连接、服务/特征值发现与断开重连,由 JLBleManager 与 JLBleEntity 承担;
  2. OTA 数据下发:将固件包按 MTU 拆分为小包并串行写入蓝牙特征值,由 SingleDataSender 实现带流控的分包发送;
  3. 协议解析:解析设备广播包与应答数据,由 JLBleHandler、HandleBroadcastPtl 承担;
  4. 多设备形态支持:除直连外还支持"通过助手设备中转"(JLBleAssistManager)与"广播音箱"(DeviceManager)两类场景。

原生层大量复用杰理自研的 DFUnits.framework 工具库(AES 加解密、CRC16 校验、Gzip 解压、HMAC-MD5、HTTP、Ping 等),这些能力直接服务于 OTA 数据包的加密、校验与固件包解压流程。

Architecture

flowchart TD
    subgraph sg_Dart["Dart 层 (Flutter)"]
        Dart["JL_OTA Dart API"]
    end

    subgraph sg_Channel["Platform Channel"]
        MC["MethodChannel"]
        EC["EventChannel"]
    end

    subgraph sg_Plugin["iOS 原生插件 (code/JL_OTA/ios/Classes)"]
        Plugin["BlePlugin.swift (插件入口)"]
        Mgr["JLBleManager (BLE 核心管理)"]
        Handler["JLBleHandler (数据处理)"]
        Sender["SingleDataSender (分包发送)"]
        Entity["JLBleEntity (设备实体)"]
        Assist["JLBleAssistManager (助手中转)"]
        Speaker["DeviceManager (广播音箱)"]
        Ptl["HandleBroadcastPtl (广播协议)"]
        Const["Constants (DeviceType/Method/Event/Log)"]
    end

    subgraph sg_System["系统与依赖"]
        CB["CoreBluetooth"]
        DF["DFUnits.framework (AES/CRC16/Gzip/HMAC-MD5/Http)"]
    end

    Dart -->|"invokeMethod / 事件监听"| MC
    MC --> Plugin
    EC --> Plugin
    Plugin --> Mgr
    Plugin --> Assist
    Plugin --> Speaker
    Mgr --> Handler
    Mgr --> Sender
    Mgr --> Entity
    Handler --> Ptl
    Assist --> CB
    Mgr --> CB
    Speaker --> CB
    Mgr --> DF
    Plugin --> Const

架构解读:

  • BlePlugin.swift 是插件对 Flutter 的唯一入口,负责注册通道、分发 Dart 发来的方法调用,并把结果/事件回传;
  • JLBleManager 是原生侧的中枢,所有直连场景的扫描、连接、数据收发都汇聚于此,同时它依赖 SingleDataSender 与 JLBleHandler 完成发送与解析两个方向的工作;
  • JLBleAssistManager 与 DeviceManager 是两条独立支线:前者面向"手机无法直连、需经助手设备转发"的场景,后者面向广播音箱(Broadcast Speakers)品类;
  • Constants 目录集中管理通道方法名、事件名、设备类型与日志标签,避免 Dart 与原生两侧的字符串常量漂移;
  • 底层统一依赖系统 CoreBluetooth 与杰理 DFUnits.framework(预编译二进制,头文件见 code/JL_OTA/example/ios/DFUnits.framework/Headers/)。

模块划分

iOS 原生层按职责分为六个子目录/文件组,均在 code/JL_OTA/ios/Classes/ 下:

模块主要文件职责
插件入口BlePlugin.swiftFlutter 插件注册、MethodChannel/EventChannel 桥接、方法分发
BLE 核心管理BleManager/JLBleManager.h/.mCBCentralManager 生命周期、扫描/连接/断开、外设与回调管理
设备实体BleManager/JLBleEntity.h/.m设备对象模型(标识、连接状态、广播数据等)
数据处理BleHandle/JLBleHandler.h/.m收发数据的解析/封包处理
分包发送BleManager/SingleDataSender.h/.mOTA 数据按 MTU 拆包、串行写入与流控
广播协议BleManager/HandleBroadcastPtl.h/.m广播包协议解析(设备广播信息提取)
助手中转BleByAssist/JLBleAssistManager.h/.m经助手设备(旁路设备)转发数据的 BLE 管理
广播音箱BroadcastSpeakers/BroadcastBle/DeviceManager.h/.m广播音箱类设备的连接与播放管理
常量定义Constant/*设备类型、方法通道、事件通道、日志标签常量

这种按"设备形态 + 通用能力"拆分的目录结构,其设计意图是:把直连、助手中转、广播音箱三条业务路径隔离,使核心 BLE 状态机不被特殊品类逻辑污染,同时让通用工具(分包发送、协议解析、常量)可被各路径复用。

BLE 管理机制(JLBleManager 为核心的直连路径)

直连场景的完整数据通路如下:

sequenceDiagram
    participant Dart as Dart 层
    participant Plugin as BlePlugin.swift
    participant Mgr as JLBleManager
    participant Sender as SingleDataSender
    participant Handler as JLBleHandler
    participant CB as CoreBluetooth
    participant Dev as 蓝牙设备

    Dart->>Plugin: MethodChannel 调用(扫描/连接/OTA 下发)
    Plugin->>Mgr: 分发请求
    Mgr->>CB: 扫描 / 连接外设
    CB-->>Mgr: 外设与特征值回调
    Mgr->>Handler: 上报原始数据(解析广播/应答)
    Handler-->>Mgr: 解析结果(更新 JLBleEntity)
    Mgr->>Sender: 下发 OTA 数据
    Sender->>CB: 按 MTU 拆分并写入特征值
    CB-->>Dev: 写入数据包
    Dev-->>CB: 应答
    CB-->>Sender: 写入完成回调
    Sender-->>Mgr: 发送进度/结果
    Mgr-->>Plugin: 状态、进度、日志
    Plugin-->>Dart: EventChannel 上报
  • 扫描与连接:JLBleManager 封装 CoreBluetooth 的 CBCentralManager 代理回调,将扫描结果、连接状态变化统一收敛为内部回调,再经 BlePlugin.swift 转成 Dart 可感知的事件。设备信息落在 JLBleEntity 中(推断字段:设备名、MAC/标识、连接状态、服务与特征值句柄)。
  • 数据解析:设备应答与广播数据交由 JLBleHandler / HandleBroadcastPtl 处理,后者负责从广播包中提取设备信息(推断:名称、地址、固件版本等),保证上层只面对解析后的结构化数据。
  • OTA 分包下发:固件包体积远大于单次 BLE 写入能力,SingleDataSender 将数据按设备 MTU 拆成小包、逐包写入并等待写完成回调后再发下一包(串行流控),避免缓冲区溢出导致丢包。

Platform Channel 与常量设计

原生层与 Dart 层的契约集中在 Constant/ 目录:

  • MethodChannelConstants.swift:定义 MethodChannel 名称与全部方法名常量(推断内容:scan/connect/disconnect/ota 等命令名),Dart 侧与原生侧共用同一份命名,避免魔法字符串;
  • EventChannelConstants.swift:定义事件通道名称与事件类型(推断内容:连接状态、升级进度、日志输出等),原生主动上报的通道;
  • DeviceTypeConstants.h/.m:设备类型枚举(对应不同芯片/品类的 OTA 流程分支);
  • LogConstants.swift:统一日志标签,便于在 Xcode 控制台按模块过滤原生日志。

设计意图:将跨语言契约集中为常量文件。Flutter 插件最典型的维护问题就是 Dart 与原生两侧字符串不一致导致的"方法找不到"或"事件收不到",集中常量从源头消除了这类漂移。

依赖框架:DFUnits.framework

示例工程 code/JL_OTA/example/ios/DFUnits.framework/Headers/ 下已确认的工具头文件:

AESx.h          -- AES 加解密(OTA 固件包加密)
DFCrc16.h       -- CRC16 校验(数据包完整性)
DFGzip.h        -- Gzip 解压(固件包解压)
DFHmacMD5.h     -- HMAC-MD5 摘要(鉴权/校验)
DFHttp.h        -- HTTP 客户端(在线升级/服务器交互)
DFPing.h        -- 网络连通性探测
DFTime.h        -- 时间工具
DFFile.h        -- 文件读写工具
DFSort.h        -- 排序工具
DFAudio.h       -- 音频工具
DFNotice.h      -- 通知工具
DFNetPlayer.h   -- 网络播放器(音频流)

Source: AESx.h、DFCrc16.h、DFGzip.h

DFUnits 以预编译 framework 形式集成,头文件公开但实现为二进制,这是杰理 SDK 的典型分发方式:既向接入方暴露稳定的 API,又保护底层算法实现。OTA 流程中 AES/CRC16/Gzip 的组合(加密 → 校验 → 解压)保证了固件包在蓝牙链路上的安全性、完整性与可执行性。

Configuration Options

iOS 原生层没有独立的运行时配置文件(如 plist/JSON),其"配置面"由以下三处承担:

配置位置类型作用说明
Constant/DeviceTypeConstants.h常量(设备类型)区分不同芯片/品类的 OTA 流程新增设备类型时在此扩展
Constant/MethodChannelConstants.swift常量(方法名)定义 Dart→原生命令契约Dart 与原生必须同步修改
Constant/EventChannelConstants.swift常量(事件名)定义原生→Dart 上报契约同上
DFUnits.framework预编译二进制提供 AES/CRC16/Gzip 等能力随 Xcode 工程链接,版本由 SDK 决定

接入方需要关心的原生配置项主要是:Info.plist 中的蓝牙权限描述(CoreBluetooth 使用说明)与 Capabilities 中的 Bluetooth 开关(推断,属于 Xcode 工程级配置,未在本仓库文件布局中直接体现)。

API Reference

注意:本页生成时源读取预算已耗尽,未能逐行核对各类的完整方法签名。以下仅列出已确认存在的类/文件及其职责边界;具体方法签名请以仓库源码为准。

BlePlugin.swift(插件入口)

  • 职责:注册 Flutter 插件、绑定 MethodChannel/EventChannel、接收 Dart 方法调用并分发至各管理器、将原生事件与日志回传 Dart。
  • 位置:BlePlugin.swift

JLBleManager(BLE 核心管理器)

  • 职责:CoreBluetooth 扫描、连接、断开、外设回调汇聚,是直连路径的中枢;对外暴露扫描/连接/数据下发接口,内部协调 JLBleHandler 与 SingleDataSender。
  • 位置:JLBleManager.h、JLBleManager.m

JLBleEntity(设备实体)

  • 职责:描述一个 BLE 设备(标识、状态、广播数据、连接句柄),作为 JLBleManager 与上层之间传递的设备模型。
  • 位置:JLBleEntity.h

SingleDataSender(分包发送器)

  • 职责:将大块数据按 MTU 拆分、串行写入特征值,等待每次写入回调后继续下一包,内置发送进度与结果回调。
  • 位置:SingleDataSender.h

JLBleHandler 与 HandleBroadcastPtl(数据处理与广播协议)

  • 职责:解析设备应答与广播包,将原始字节转换为结构化信息供上层使用。
  • 位置:JLBleHandler.h、HandleBroadcastPtl.h

JLBleAssistManager(助手中转)与 DeviceManager(广播音箱)

  • 职责:两条独立设备形态路径——经助手设备转发数据、以及广播音箱设备的连接/管理。
  • 位置:JLBleAssistManager.h、DeviceManager.h

Failure Modes、边界情况与并发

以下分析基于目录结构与 BLE OTA 工程的通用约束(推断项已标注):

  • 蓝牙未授权/未开启:CoreBluetooth 授权弹窗被拒或系统蓝牙关闭时,扫描/连接必然失败。原生层应在 JLBleManager 的 central manager 状态回调处识别 CBCentralManagerState 异常并通过 EventChannel 上报(推断),提示用户在系统设置中开启权限。
  • 连接中断与断点续传:OTA 过程中设备远离或断电会导致链路断开。分包发送(SingleDataSender)若中断,需支持重连后的状态恢复或重新开始(推断:由上层决定续传策略,原生层需保证发送状态可查询)。
  • MTU 与缓冲区溢出:若一次写入超过设备 MTU 或在上一个写入完成前就写入下一包,会造成丢包/卡死。SingleDataSender 采用"写回调后再发下一包"的串行模式正是为了规避该问题。
  • 数据校验失败:链路层干扰可能导致包损坏。DFUnits 的 CRC16 与 AES 能力用于校验/解密,校验失败时应触发重发或终止流程(推断)。
  • 并发/竞态:BLE 回调(centralManager 代理)与业务线程之间、以及多设备并发连接时,共享状态(如当前发送队列、连接句柄)需要串行保护;JLBleManager 作为单一中枢降低了竞态面,但发送队列的线程安全依赖其内部实现(未验证)。

Performance 与运维注意事项

  • 分包粒度与流控:OTA 传输吞吐直接取决于 MTU 协商与 SingleDataSender 的写入节奏。支持更大 MTU(如通过 maximumWriteValueLength 协商,推断)可显著减少包数量、降低总耗时;串行写入保证了吞吐与可靠性的平衡。
  • 预编译 framework 集成:DFUnits.framework 以二进制形式随工程分发,接入方无需编译其源码,但升级 SDK 时需同步替换 framework 并核对头文件兼容性。该目录位于示例工程 code/JL_OTA/example/ios/ 下,插件仓库与示例工程共用同一套依赖布局。
  • 日志可观测性:LogConstants.swift 提供统一日志标签,联调时可按标签过滤原生侧日志,快速定位扫描、连接、发送各环节问题(推断:日志经 EventChannel 上报 Dart 层展示)。
  • 状态上报频率:升级进度事件若逐包上报会刷爆通道,合理做法是聚合进度(如按百分比或按块)后经 EventChannel 上报(推断),降低 Dart 侧渲染与通道开销。

Extension Points

  • 新增设备类型/芯片:在 Constant/DeviceTypeConstants.h 增加类型常量,并在对应业务路径(直连/助手/音箱)中扩展流程分支。这是最常规的扩展入口。
  • 新增方法通道命令:在 MethodChannelConstants.swift 增加方法名,同时在 BlePlugin.swift 的分发逻辑中注册对应处理分支,并保持 Dart 侧同步。
  • 新增协议解析:在 BleManager 目录下仿照 JLBleHandler / HandleBroadcastPtl 增加协议处理类,由 JLBleManager 在收到原始数据时按协议类型分发。
  • 新增设备形态:仿照 BleByAssist 与 BroadcastSpeakers 目录结构,新增独立子目录承载专属管理类,避免把品类逻辑塞进通用 JLBleManager——这正是现有目录划分所鼓励的扩展方式。

Tests

本次探索未在 code/JL_OTA/ios/ 与 code/JL_OTA/example/ios/ 中发现独立的 iOS 原生单元测试工程(未找到 *Tests 目标或 XCTest 源文件)。BLE 设备相关逻辑强依赖真实硬件,实践中多以真机 + 实体设备联调为主(推断)。若后续仓库补充 XCTest/UI 测试,建议优先覆盖 SingleDataSender 的分包边界与 HandleBroadcastPtl 的广播解析等纯逻辑部分。

Related Links

  • Android 原生层架构:Android 侧对应实现,通道契约与 iOS 侧保持一致
  • BlePlugin.swift:iOS 插件入口源文件
  • JLBleManager.h:BLE 核心管理器
  • MethodChannelConstants.swift:方法通道常量契约
  • DFUnits.framework Headers:依赖工具库头文件目录
Prev
Android 原生层
Next
iOS 蓝牙管理与 SDK 运行