iOSMcuManagerLibrary 1.7.1

iOSMcuManagerLibrary 1.7.1

Aleksander NowakowskiDinesh Harjani 维护。



 
依赖项
SwiftCBOR= 0.4.7
ZIPFoundation= 0.9.19
 

  • Dinesh Harjani 和 Aleksander Nowakowski

Platforms License Release Swift Package Manager Compatible

nRF Connect Device Manager

nRF Connect Device Manager 库与 McuManager (McuMgr, 简称) 兼容,McuManager 是 nRF Connect SDKZephyr 和 Apache Mynewt 支持的管理子系统。它将成为新北斗设备的推荐协议,不应与旧的协议 NordicDFU 混淆,NordicDFU 由 旧 DFU 库 提供。McuManager 使用 简单管理协议,或 SMP,从兼容设备发送和接收消息请求。该库实现的蓝牙低功耗 SMP 传输定义可在此处找到 这里

该库提供了一个与传输无关的 McuManager 协议实现。它包含 BLE 传输的默认实现。

最低要求的 iOS 版本是 9.0,最初于 2015 年秋季发布。

注意

此存储库是 McuManager iOS 库 的分支,该库的原维护者不再支持它。截至 2021 年,我们已拥有该库,因此所有新功能和错误修复将在此处添加。请将您的项目迁移到指向此 Git 存储库以获取未来的更新。有关迁移指南,请参阅 迁移指南

兼容设备

nRF52 系列产品 nRF53 系列产品 nRF91 系列产品

此库旨在通过 BLE 使用 SMP 传输。它由 Nordic Semiconductor 实现,也可由任何芯片实现和维护,只要通过 SMP 协议通信。如果您遇到与任何芯片(不仅限于 Nordic)通信的问题,请提交 Issue。

将库集成到现有项目中(安装)

在 Xcode 中打开您的根项目文件。然后,切换到 Package Dependencies 选项卡,并点击您列表下方的 + 按钮。一个新窗口将弹出。在此新窗口的右上角,有一个搜索框。粘贴此 GitHub 项目的 URL https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager,并应启用 添加包 按钮。

在 Xcode 下载您的项目依赖项后,现在您应该能够向 Swift 文件中添加 import iOSMcuManagerLibrary,以调用此库。一切正常。

CocoaPods

pod 'iOSMcuManagerLibrary'

构建示例项目(需要 Xcode 和 CocoaPods)

"Cocoapods?"

不必担心,我们将为你提供支持。只需按照此处说明操作

说明

首先,克隆项目

git clone https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager.git

然后,打开项目的目录,导航到Example文件夹,并运行pod install

cd IOS-nRF-Connect-Device-Manager/
cd Example/
pod install

输出应该看起来类似于这个

Analyzing dependencies
Downloading dependencies
Installing SwiftCBOR (0.4.4)
Installing ZIPFoundation (0.9.11)
Installing iOSMcuManagerLibrary (1.3.1)
Generating Pods project
Integrating client project
Pod installation complete! There are 2 dependencies from the Podfile and 3 total pods installed.

现在你应该能够通过打开nRF Connect Device Manager.xcworkspace文件来打开、构建和运行Example项目

open nRF\ Connect\ Device\ Manager.xcworkspace

简介

McuManager是一个用于管理和监控运行Apache Mynewt和Zephyr的微控制器的应用层协议。更具体地说,McuManager实现了空中(OTA)固件升级、日志和状态收集,以及文件系统和配置管理。

命令组

McuManager按功能组织成命令组。在mcumgr-ios中,命令组被称为管理器,并且扩展了McuManager类。在mcumgr-ios中实施的管理器(组)包括:

  • DefaultManager:包含与操作系统相关的命令。这包括任务和内存池统计信息、设备时间读取和写入以及设备复位。
  • ImageManager:管理设备上的镜像状态并执行镜像上传。
  • StatsManager:从设备中读取状态。
  • SettingsManager:在设备上读取/写入配置值。
  • LogManager:从设备中收集日志。
  • CrashManager:在设备上运行崩溃测试。
  • RunTestManager:在设备上运行测试。
  • FileSystemManager:从设备文件系统下载/上传文件。
  • BasicManager:向设备发送“擦除应用程序设置”命令。

固件升级

固件升级通常是四个步骤的过程,使用来自imagedefault命令组的命令执行:upload(上传)、test(测试)、reset(复位)和confirm(确认)。

此库提供FirmwareUpgradeManager方便在设备上升级运行的镜像。

FirmwareUpgradeManager

FirmwareUpgradeManager提供了一种简单的方法来在设备上执行固件升级。必须使用定义传输方案和设备的McuMgrTransport来初始化FirmwareUpgradeManager。一旦初始化完成,一个FirmwareUpgradeManager就可以同时执行一个固件升级。使用start(data: Data)方法启动固件升级,并使用pause()resume()cancel()分别暂停、恢复和取消。

Legacy / App Core-Only 升级示例

// Initialize the BLE transporter using a scanned peripheral
let bleTransport = McuMgrBleTransport(cbPeripheral)

// Initialize the FirmwareUpgradeManager using the transport and a delegate
let dfuManager = FirmwareUpgradeManager(bleTransport, delegate)

// Start the firmware upgrade with the image data
dfuManager.start(data: imageData)

注意:始终从主线程开始/pause/cancel DFU API调用。

多镜像DFU示例

extension ImageManager {
    
    public typealias Image = (image: Int, data: Data)

    [...]
}

上述是针对多镜像DFU调用输入的格式,其中image参数的0表示App Core1表示 Net Core。当然,随着我们产品功能的扩展,这些分配当然会发生变化。

有了这些,开始为任一或两个核心调用DFU变得很简单

// Initialize the BLE transporter using a scanned peripheral
let bleTransport = McuMgrBleTransport(cbPeripheral)

// Initialize the FirmwareUpgradeManager using the transport and a delegate
let dfuManager = FirmwareUpgradeManager(bleTransport, delegate)

// Build Multi-Image DFU parameters
let images: [ImageManager.Image] = [
    (image: 0, data: appCoreData), // App Core
    (image: 1, data: netCoreData) // Net Core
]

// Start Multi-Image DFU firmware upgrade
dfuManager.start(images: images)

多镜像DFU格式

通常,在执行多镜像DFU时,每个核心附加图像的交付格式将是一个.zip文件。这是因为.zip文件允许我们将必要的信息捆绑在一起,包括每个核心的图像以及应该上传到每个核心的图像。图像文件(通常为.bin格式)与应上传到的核心之间的关联是写在一个强制性的JSON格式的Manifest,被称为清单。这个manifest.json是我们nRF Connect SDK作为我们Zephyr构建系统的一部分生成的,如此处文档所述。您可以在库中的McuMgrManifest结构体定义中了解清单中包含的信息。

现在的问题是,之前提到的SDK和我们的Zephyr构建系统输出之间存在差距,这是由一个.zip文件组成的。为了弥合这一差距,我们编写了McuMgrPackage,它在其init()函数中接受一个URL。因此,给定指向.zip文件的URL,可以像这样开始多重映像DFU

do {
    // Initialize the BLE transporter using a scanned peripheral
    let bleTransport = McuMgrBleTransport(cbPeripheral)

    // Initialize the FirmwareUpgradeManager using the transport and a delegate
    let dfuManager = FirmwareUpgradeManager(bleTransport, delegate)

    // Read Multi-Image DFU package
    let dfuPackage = try McuMgrPackage(from: dfuPackageUrl)

    // Start Multi-Image DFU firmware upgrade
    dfuManager.start(images: dfuPackage.images)
} catch {
    // try McuMgrPackage(from:) will throw McuMgrPackage.Error(s) here.
}

查看示例项目中的FirmwareUpgradeViewController.swift以获取更详细的用法示例。

固件升级模式

可以通过略有不同的程序进行McuManager的固件升级。这些不同的升级模式决定了在上传步骤后的命令。可以通过设置FirmwareUpgradeManager中的configuration属性来配置FirmwareUpgradeManager执行这些升级变化,如下所述。(注:之前是在FirmwareUpgradeManagermode属性中设置,现已删除)不同的固件升级模式如下

  • .testAndConfirm:这种模式是执行升级的默认且推荐模式,因为它能够从失败的固件升级中恢复。该模式的流程为上传测试重置确认
  • .confirmOnly:除非是多重映像DFU,否则不推荐使用这种模式,因为它是唯一支持的DFU模式。如果设备无法启动到新映像,则无法恢复,并需要重新编程。该模式的流程为上传确认重置
  • .testOnly:如果在确认作为主要启动映像之前想要对新映像运行测试,则此模式很有用。该模式的流程为上传测试重置
  • .uploadOnly:这是一个非常特殊的模式。它不监听或识别引导加载程序信息,只通过上传然后是重置来跨越升级过程。就是这样。由于这不是默认的,因此用户必须决定这是否是正确的模式。

固件升级状态

FirmwareUpgradeManager是一个简单的主要是线性的状态机,由mode决定。管理器在学习固件升级过程中,通过FirmwareUpgradeDelegateupgradeStateDidChange方法提供状态变化。

FirmwareUpgradeManager包含一个额外的状态validate,它在上传之前进行。该validate状态检查设备的当前映像状态,以绕过固件升级的某些状态。例如,如果要升级的映像已经存在于设备的插槽1中,则FirmwareUpgradeManager将跳过上传并直接从validate移动到测试(或如果已设置.confirmOnly模式,则为确认)。如果已上传的映像已经是活动的,并且在插槽0中已确认,则升级将立即成功。简而言之,validate状态使得重新尝试升级变得更容易,无需重新上传映像或手动确定从哪里开始。

固件升级配置

nRF53 Dual-Core SoC Diagram, which supports all of these features.

在1.2版本中,引入了新功能以提高上传速度,这是在Android端首先完成的工作,并且所有这些功能都可以通过新的FirmwareUpgradeConfiguration结构体获得。

  • pipelineDepth:(在示例应用的UI中表示为‘缓冲区数量’。)对于大于1的值,此功能启用SMP流水线功能。这意味着并发发送多个写入数据包,从而在接收设备配置的缓冲区数量越多,提供更大的速度提升。默认设置为1(缓冲区数量 = 禁用)。
  • byteAlignment:在使用SMP流水线时需要进行设置。通过固定每个数据块的大小,我们可以预测接收设备偏移量的跳转,因此可以同时平稳地发送多个数据包。当未使用SMP流水线(pipelineDepth设置为1)时,库仍然执行字节对齐(如果已设置),但它对于更新的工作不是必须的。默认设置为ImageUploadAlignment.disabled
  • reassemblyBufferSize:SMP重组是另一个提高速度的功能。它适用于运行NCS 2.0固件或更高版本的设备,并且是自动调整的。在开始上传之前,通过DefaultManager发送请求以获取MCU管理器参数。如果收到这些参数,这意味着固件可以接受比MTU大小更大的数据块,从而提高速度。该属性将反映接收设备上的缓冲区大小,McuMgrBleTransport将在同一序列号内分块数据,确保每个数据包传输都在MTU边界内。SMP重组无需额外工作即可工作 - 如果不支持,则MCU管理器参数请求将失败,上传将假定没有重组功能而继续进行。
  • eraseAppSettings:这不是一个与速度相关的特性。将此设置为true意味着将擦除设备上的所有应用程序数据,包括绑定信息、步数、登录或其他任何事情。如果在更新后的新固件中有任何主要数据更改,如功能完全更改或带有不同保存结构的新更新,这将是推荐的。默认设置为true
  • upgradeMode:固件升级模式。详见上面章节中关于所有可能的升级模式的深入解释。
  • bootloaderMode:引导加载程序模式不一定有意作为一个设置。如果目标固件对引导加载程序信息请求没有提供有效的响应,它会被视为一个设置,例如,如果不支持它。它所做的就是在iOSMcuMgrLibrary中通知支持的操作。例如,如果upgradeMode设置为confirmOnly但引导加载程序处于DirectXIP状态且没有Revert模式,发送确认命令将返回错误。这意味着,即使upgradeMode被设置,也不会发送确认命令。所以是的,这是我们从SMP / McuManager必须处理的另一层复杂性。

配置示例

这是开始DFU的自定义FirmwareUpgradeConfiguration的方式

// Setup
let bleTransport = McuMgrBleTransport(cbPeripheral)
let dfuManager = FirmwareUpgradeManager(bleTransport, delegate)

// Non-Pipelined Example
let nonPipelinedConfiguration = FirmwareUpgradeConfiguration(
    estimatedSwapTime: 10.0, eraseAppSettings: false, pipelineDepth: 2,
)

// Legacy / App-Core Only DFU Example
dfuManager.start(data: imageData, using: nonPipelinedConfiguration)

// Pipelined Example
let pipelinedConfiguration = FirmwareUpgradeConfiguration(
    estimatedSwapTime: 10.0, eraseAppSettings: true, pipelineDepth: 4,
    byteAlignment: .fourByte
)

// Multi-Image DFU Example
dfuManager.start(images: images, using: pipelinedConfiguration)

注意:您当然可以混合和匹配配置和要上传的图像的输入参数类型。

日志记录

在管理器中设置logDelegate属性提供对底层日志的访问,这可以帮助调试应用程序和您的设备。消息根据6个日志级别进行记录,从.debug.error,并包含一个McuMgrLogCategory,该类识别原始组件。此外,McuMgrBleTransportlogDelegate属性提供了对BLE传输日志的访问。

示例

// Initialize the BLE transporter using a scanned peripheral
let bleTransport = McuMgrBleTransport(cbPeripheral)
bleTransporter.logDelegate = UIApplication.shared.delegate as? McuMgrLogDelegate

// Initialize the DeviceManager using the transport and a delegate
let deviceManager = DeviceManager(bleTransport, delegate)
deviceManager.logDelegate = UIApplication.shared.delegate as? McuMgrLogDelegate

// Send echo
deviceManger.echo("Hello World!", callback)

OSLog集成

McuMgrLogDelegate可以轻松集成到统一日志系统中。一个示例可在示例应用程序的AppDelegate.swift文件中找到。在该文件中可以找到一个McuMgrLogLevel扩展,它可以将其转换为OSLogType级别之一。类似地,McuMgrLogCategory扩展将类别转换为OSLog类型。

相关项目

我们听到了开发者需要一个针对多个平台的目标单一McuMgr DFU库的需求。因此,我们提供了一个Flutter库作为Android和iOS的包装器。