更新时间:2024-08-22 03:21:17下载pdf
固件升级是指把新的固件写入芯片中,代替原有的固件的过程。随着市场变化、开发方案升级等原因,涂鸦会定期进行固件更新。同时,涂鸦会根据原厂芯片迭代等情况,对部分旧版本进行停用。另外,设备本身也可以进行功能更新迭代,从而升级固件。
使用查询设备升级信息接口,可以查询到 ThingSmartFirmwareUpgradeModel
固件升级模型。其中:
upgradeMode
属性表示固件类别。type
属性表示固件通道类型。typeDesc
属性表示固件类型的描述。固件类别
查询固件列表时,ThingSmartFirmwareUpgradeModel
中有 upgradeMode
字段:
普通固件:字段取值为 0
。传统意义上的固件,用于升级设备内固件。
PID 版本升级固件:字段取值为 1
。引入产品版本的概念,不同版本间的数据能在指定功能模组范围内(即产品 schema 配置、面板配置、多语言配置、快捷控制配置)进行隔离配置。
需要使用新接口获取固件列表、发起升级。
固件通道类型
作为标识 普通固件 的固件通道,在查询固件列表时,ThingSmartFirmwareUpgradeModel
中 type
字段为固件通道类型,可以通过typeDesc
来获取到具体的描述。
通常通道 type
含义如下表所示,推荐根据实际情况使用模型返回的 typeDesc
来标识实际固件描述。
普通固件通道 type | 固件通道含义 |
---|---|
0 | 主联网模组、Wi-Fi 模组、蓝牙模组 |
1 | 蓝牙模组 |
2 | GPRS 模组 |
3 | Zigbee 模组 |
5 | 433 模组 |
6 | NB-IoT 模组 |
9 | MCU 模组 |
10 ~ 19 | 扩展通道 |
接口说明
// 获取普通固件及 PID 版本升级固件
- (void)checkFirmwareUpgrade:(void (^)(NSArray<ThingSmartFirmwareUpgradeModel *> *firmwares))success failure:(nullable ThingFailureError)failure;
// 废弃,仅获取普通固件
- (void)getFirmwareUpgradeInfo:(nullable void (^)(NSArray <ThingSmartFirmwareUpgradeModel *> *upgradeModelList))success failure:(nullable ThingFailureError)failure;
参数说明
参数 | 说明 |
---|---|
success | 成功回调,设备的固件升级信息列表 |
failure | 失败回调 |
ThingSmartFirmwareUpgradeModel
数据模型
字段 | 类型 | 说明 |
---|---|---|
desc | NSString | 升级文案 |
type | NSInteger | 固件通道类型,普通固件使用 |
typeDesc | NSString | 固件通道描述 |
upgradeStatus | NSInteger |
|
version | NSString | 新版本使用的固件版本 |
currentVersion | NSString | 当前的固件版本 |
devType | NSInteger |
|
upgradeType | NSInteger |
|
url | NSString | 蓝牙设备的升级固件包下载 URL |
fileSize | NSString | 固件包的大小,单位为字节 (byte),fileSize 仅支持蓝牙设备 |
md5 | NSString | 固件的 MD5 |
controlType | BOOL |
|
waitingDesc | NSString | 固件等待设备唤醒的文案 |
upgradingDesc | NSString | 固件升级中的提示文案 |
canUpgrade | NSNumber |
|
remind | NSString | 前置校验规则未通过的提示文案 |
upgradeMode | ThingSmartDeviceUpgradeMode | 固件类别,从 3.35.5 版本开始支持
|
示例代码
Objective C:
- (void)getFirmwareUpgradeInfo {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
[self.device checkFirmwareUpgrade:^(NSArray<ThingSmartFirmwareUpgradeModel *> *upgradeModelList) {
NSLog(@"getFirmwareUpgradeInfo success");
} failure:^(NSError *error) {
NSLog(@"getFirmwareUpgradeInfo failure: %@", error);
}];
}
Swift:
func getFirmwareUpgradeInfo() {
device?.checkFirmwareUpgrade({ (upgradeModelList) in
print("getFirmwareUpgradeInfo success")
}, failure: { (error) in
if let e = error {
print("getFirmwareUpgradeInfo failure: \(e)")
}
})
}
这里只会返回正在升级的固件。若没有正在升级的固件,则回调 failure
。
接口说明
- (void)getFirmwareUpgradingStatus:(void (^)(ThingSmartFirmwareUpgradeStatusModel *status))success failure:(nullable ThingFailureError)failure
参数说明
参数 | 说明 |
---|---|
success | 成功回调,升级状态模型 |
failure | 失败回调,表示设备没有在升级或查询失败 |
ThingSmartFirmwareUpgradeStatusModel
数据模型
字段 | 类型 | 说明 |
---|---|---|
upgradeStatus | ThingSmartDeviceUpgradeStatus | 升级状态枚举:
|
statusText | NSString | 状态描述 |
statusTitle | NSString | 状态标题 |
progress | NSInteger | 进度,部分情况下,参数值可能小于 0,请忽略此种小于 0 的进度 |
type | NSInteger | 固件通道类型,在确认升级时需要使用到 |
upgradeMode | ThingSmartDeviceUpgradeMode |
|
error | NSError | 失败信息 |
示例代码
Objective C:
- (void)getFirmwareUpgradeInfo {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
[self.device getFirmwareUpgradingStatus:^(ThingSmartFirmwareUpgradeStatusModel *status) {
NSLog(@"getFirmwareUpgradingStatus success");
} failure:^(NSError *error) {
NSLog(@"getFirmwareUpgradingStatus failure: %@", error);
}];
}
Swift:
func getFirmwareUpgradeInfo() {
device?.getFirmwareUpgradingStatus({ (status) in
print("getFirmwareUpgradingStatus success")
}, failure: { (error) in
if let e = error {
print("getFirmwareUpgradingStatus failure: \(e)")
}
})
}
接口说明
// 支持普通固件以及 PID 版本升级固件
// 在原本的基础上支持单点蓝牙、蓝牙 Mesh、动态网关等设备的升级
// 同一设备的多个固件可以依次升级
// firmewares: 需要升级的固件,通过接口 checkFirmwareUpgrade 获取
- (void)startFirmwareUpgrade:(NSArray<ThingSmartFirmwareUpgradeModel *> *)firmwares
// 废弃,推荐使用通过 - startFirmwareUpgrade: 发起升级
// 仅支持普通固件,仅支持有 Wi-Fi 能力的设备以及 Zigbee 子设备,无法支持单点蓝牙、蓝牙 Mesh、动态网关等设备
// 仅能发起单个固件升级
// type:需要升级的类型,从设备升级信息接口 getFirmwareUpgradeInfo 获取
- (void)upgradeFirmware:(NSInteger)type success:(nullable ThingSuccessHandler)success failure:(nullable ThingFailureError)failure;
参数说明
-startFirmwareUpgrade:
接口参数说明
参数 | 说明 |
---|---|
firmwares | 从设备升级信息接口 getFirmwareUpgradeInfo 获取的固件列表 |
-upgradeFirmware:success:failure:
接口参数说明
参数 | 说明 |
---|---|
type | type: 需要升级的类型,从设备升级信息接口 getFirmwareUpgradeInfo 获取 |
success | 成功回调 |
failure | 失败回调 |
通过设备升级信息接口 getFirmwareUpgradeInfo
获取的信息列表中会包含下列状态信息:
无新版本(upgradeStatus: 0)
有新版本(upgradeStatus: 1)
在升级中(upgradeStatus: 2)
等待设备唤醒(upgradeStatus: 5)
上述状态信息用于展示升级相关状态。仅 有新版本(upgradeStatus: 1)状态时,可以发起升级。请在使用做好相关过滤和状态展示。
部分设备有前置校验限制。通过 getFirmwareUpgradeInfo
获取信息列表,采用其中任何一个升级信息模型 ThingSmartFirmwareUpgradeModel
对象中的 canUpgrade
进行判断。
判断说明 | 判断依据 |
---|---|
无需前置校验,可以升级 | canUpgrade == nil |
有前置校验,且校验未通过,无法升级 | canUpgrade != nil && canUpgrade.integerValue == 0 |
有前置校验,且校验通过,可以升级 | canUpgrade != nil && canUpgrade.integerValue == 1 |
若有前置校验,且校验未通过,无法升级的,可以通过 remind
获取不可升级的说明文案。
示例代码
Objective C:
- (void)upgradeFirmwareNew {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
// firmwares:从获取设备升级信息接口 checkFirmwareUpgrade 返回的固件列表
// 注意,根据上述注意事项过滤掉不符合规则的固件
[self.device startFirmwareUpgrade:firmwares];
}
Swift:
func upgradeFirmware() {
// firmwares:从获取设备升级信息接口 getFirmwareUpgradeInfo 返回的固件列表
// 注意,根据上述注意事项过滤掉不符合规则的固件
device?.startFirmwareUpgrade(firmwares);
}
目前仅支持在升级中收到进度回调时,error.code
为 ThingOTAErrorCodeSignalStrengthNotSatisfy
的场景。
在升级 Wi-Fi 和双模类设备时,为保证升级通畅,通常会设置一个最低的信号强度。当发起升级时,会检查设备的信号强度是否符合。不符合,则会回调进度状态 error.code = ThingOTAErrorCodeSignalStrengthNotSatisfy
。此时,可以通过 UI 交互,让用户做选择。例如,弹窗提示 设备信号弱,升级可能失败,是否继续升级? 等文案。
接口说明
- (void)confirmWarningUpgradeTask:(BOOL)isContinue;
参数说明
参数 | 说明 |
---|---|
isContinue | 是否继续升级 |
仅通过 -startFirmwareUpgrade:
发起的升级,才有此流程。
示例代码
Objective C:
- (void)continueFirmware {
// isContinue 由用户选择是否继续
[self.device confirmWarningUpgradeTask:isContinue];
}
Swift:
func continueFirmware() {
// isContinue 由用户选择是否继续
device?.confirmWarningUpgradeTask(isContinue)
}
目前仅支持低功耗类型的设备。此类设备在发起升级后,可能处于 待唤醒状态(upgradeStatus
= 5
)。通过此方法,可以取消待唤醒的升级任务。
接口说明
// 目前仅支持取消低功耗类型的设备
- (void)cancelFirmwareUpgrade:(ThingSuccessHandler)success
failure:(nullable ThingFailureError)failure;
// 方法废弃,推荐使用 -cancelFirmwareUpgrade:failure:
// type:从设备升级信息接口 getFirmwareUpgradeInfo 获取
- (void)cancelUpgradeFirmware:(NSInteger)type success:(nullable ThingSuccessHandler)success failure:(nullable ThingFailureError)failure;
参数说明
参数 | 说明 |
---|---|
success | 成功回调 |
failure | 失败回调 |
取消待唤醒的升级,仅适用于 upgradeStatus
为 5
(等待设备唤醒)的设备。
示例代码
Objective C:
- (void)cancelFirmware {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
// 仅适用于 upgradeStatus 为 5(等待设备唤醒)的设备
[self.device cancelFirmwareUpgrade:^{
NSLog(@"cancel success");
} failure:^(NSError *error) {
NSLog(@"cancel failure: %@", error);
}];
}
Swift:
func cancelFirmware() {
// 仅适用于 upgradeStatus 为 5(等待设备唤醒)的设备
device?.cancelFirmwareUpgrade(success: {
print("cancel success")
}, failure: { (error) in
if let e = error {
print("cancel failure: \(e)")
}
})
}
通过 -startFirmwareUpgrade:
发起的升级,推荐使用 -device:otaUpdateStatusChanged:
回调。此回调包含状态变化、进度更新、失败原因。其他废弃回调方法,也依然会回调。为了防止重复的回调监听,建议将相关逻辑迁移至此回调。
示例代码
Objective C:
- (void)device:(ThingSmartDevice *)device otaUpdateStatusChanged:(ThingSmartFirmwareUpgradeStatusModel *)statusModel {
// 固件升级状态和升级进度回调。
// 推荐与 -startFirmwareUpgrade: 配套使用
}
- (void)device:(ThingSmartDevice *)device firmwareUpgradeStatusModel:(ThingSmartFirmwareUpgradeStatusModel *)upgradeStatusModel {
// 固件升级状态回调。
// 推荐与 -upgradeFirmware:success:failure: 配套使用
}
- (void)deviceFirmwareUpgradeSuccess:(ThingSmartDevice *)device type:(NSInteger)type {
// 固件升级成功。方法废弃,推荐使用 - device:firmwareUpgradeStatusModel:
}
- (void)deviceFirmwareUpgradeFailure:(ThingSmartDevice *)device type:(NSInteger)type {
// 固件升级失败。方法废弃,推荐使用 - device:firmwareUpgradeStatusModel:
}
- (void)device:(ThingSmartDevice *)device firmwareUpgradeProgress:(NSInteger)type progress:(double)progress {
// 固件升级的进度。
// 推荐与 -upgradeFirmware:success:failure: 配套使用
}
Swift:
func device(_ device: ThingSmartDevice, firmwareUpgradeStatusModel upgradeStatusModel: ThingSmartFirmwareUpgradeStatusModel) {
//设备升级状态变更
}
func deviceFirmwareUpgradeSuccess(_ device: ThingSmartDevice!, type: Int) {
//固件升级成功,即将弃用,推荐使用 device(_:, firmwareUpgradeStatusModel:)
}
func deviceFirmwareUpgradeFailure(_ device: ThingSmartDevice!, type: Int) {
//固件升级失败,即将弃用,推荐使用 device(_:, firmwareUpgradeStatusModel:)
}
func device(_ device: ThingSmartDevice!, firmwareUpgradeProgress type: Int, progress: Double) {
//固件升级的进度
}
部分设备支持自动保持最新版本。通过 ThingSmartDeviceModel - supportAuto
来判断设备是否支持该功能。
接口说明
// 获取开关状态
- (void)getAutoUpgradeSwitchInfoWithSuccess:(nullable ThingSuccessID)success
failure:(nullable ThingFailureError)failure;
// 保存开关状态
- (void)saveUpgradeInfoWithSwitchValue:(NSInteger)switchValue
success:(nullable ThingSuccessHandler)success
failure:(nullable ThingFailureError)failure;
参数说明
参数 | 说明 |
---|---|
switchValue | 功能状态:
|
success | 成功回调 |
failure | 失败回调 |
示例代码
Objective C:
- (void)getAutoUpgradeSwitchInfo {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
// 注意需先通过 ThingSmartDeviceModel - supportAuto 来判断是否设备支持
[self.device getAutoUpgradeSwitchInfoWithSuccess:^(NSNumber *status) {
// 0:关闭, 1:开启。此处样例为:关闭
NSLog(@"current switch status: %@", status);
} failure:^(NSError *error) {
NSLog(@"get current switch status fail. %@", error);
}];
}
- (void)saveAutoUpgradeSwitchInfo {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
// 注意,需先通过 ThingSmartDeviceModel - supportAuto 来判断设备是否支持
NSInteger status = 0; // 0:关闭, 1:开启。此处样例为:关闭
[self.device saveUpgradeInfoWithSwitchValue:status success:^{
NSLog(@"save auto switch status success.");
} failure:^(NSError *error) {
NSLog(@"save auto switch status fail. %@", error);
}];
}
Swift:
func getAutoUpgradeSwitchInfo() {
// 注意,需先通过 ThingSmartDeviceModel - supportAuto 来判断设备是否支持
device?.getAutoUpgradeSwitchInfo(success: { status in
// 0:关闭, 1:开启。
if let value = status {
print("get current status: \(value)")
}
}, failure: { error in
if let e = error {
print("get status failure: \(e)")
}
})
}
func saveAutoUpgradeSwitchInfo() {
// 注意,需先通过 ThingSmartDeviceModel - supportAuto 来判断设备是否支持
let status = 0 // 0:关闭, 1:开启。此处样例为:关闭
device?.saveUpgradeInfo(withSwitchValue: 0, success: {
print("save success")
}, failure: { error in
if let e = error {
print("success failure: \(e)")
}
})
}
此接口从 5.1.0 版本 SDK 开始提供。
接口说明
- (void)memberCheckFirmwareStatus:(void (^)(NSArray<ThingSmartMemberCheckFirmwareInfo *> *infos))success
failure:(ThingFailureError)failure;
参数说明
参数 | 说明 |
---|---|
success | 成功回调 |
failure | 失败回调 |
ThingSmartMemberCheckFirmwareInfo
数据模型
字段 | 类型 | 说明 |
---|---|---|
type | NSInteger | 固件通道类型 |
upgradeStatus | NSInteger |
|
version | NSString | 新版本使用的固件版本 |
upgradeText | NSString | 固件升级信息 |
示例代码
Objective C:
- (void)memberCheckFirmwareStatus {
// self.device = [ThingSmartDevice deviceWithDeviceId:@"your_device_id"];
[self.device memberCheckFirmwareStatus:^(NSArray<ThingSmartMemberCheckFirmwareInfo *> * _Nonnull infos) {
NSLog(@"member check success");
} failure:^(NSError *error) {
NSLog(@"member check failure");
}];
}
Swift:
func memberCheckFirmwareStatus() {
device?.memberCheckFirmwareStatus(success: { infos in
print("member check success: \(infos)")
}, failure: { error in
if let e = error {
print("member check failure: \(e)")
}
})
}
ThingSmartFirmwareUpgradeStatusModel
中的 error
属性 的 code
,仅在通过新升级接口时可用。
错误码 | 说明 | 备注 |
---|---|---|
5000 | 设备所有固件已是最新,无需升级 | - |
5001 | 未检查到固件 | - |
5002 | 蓝牙类设备同时只能有一个设备在升级 | 通常为蓝牙单点、涂鸦 Mesh 子设备、蓝牙 Mesh 子设备 |
5003 | App 下载固件包失败 | - |
5004 | 获取是否需要信号强度检测失败 | - |
5005 | 设备信号强度不满足升级条件 | 建议询问用户是否继续,继续可能会失败,可通过接口 - confirmWarningUpgradeTask: 继续或者取消 |
5006 | 连接设备失败 | 通常为蓝牙单点、涂鸦 Mesh 子设备、蓝牙 Mesh 子设备 |
5007 | 将蓝牙单点设备从网关下解绑超时 | - |
5009 | App 下载固件 MD5 校验不通过 | - |
5010 | App 发送固件失败 | 通常为蓝牙单点、涂鸦 Mesh 子设备、蓝牙 Mesh 子设备 |
5012 | 设备不在线 | - |
5013 | 升级前置校验不通过 | - |
5014 | 手机蓝牙未打开 | - |
5015 | 可升级固件列表接口请求失败 | - |
5016 | 设备升级超时 | - |
5017 | 调用发起 OTA 升级接口失败 | 服务端返回接口调用错误,详细错误码通过 error.localizedFailureReason 获取,详细描述通过 error.localizedDescription 获取 |
5018 | 设备升级中失败,设备上报失败原因 | 详细描述通过 error.localizedDescription 获取 |
5099 | 通用错误码 | - |
功能 | 新接口 | 老接口 |
---|---|---|
查询升级信息 | checkFirmwareUpgrade:failure: |
getFirmwareUpgradeInfo:failure: |
查询设备正在升级的固件状态 | getFirmwareUpgradingStatus:failure: |
无 |
开始升级 | startFirmwareUpgrade: |
upgradeFirmware:success:failure: |
取消升级 | cancelFirmwareUpgrade:failure: |
cancelUpgradeFirmware:succes:failure: |
回调监听 | device:otaUpdateStatusChanged: |
device:firmwareUpgradeStatusModel: deviceFirmwareUpgradeSuccess:type: deviceFirmwareUpgradeFailure:type: device:firmwareUpgradeProgress: |
source 'https://github.com/tuya/tuya-pod-specs.git'
platform :ios, '11.0'
target 'Your_Project_Name' do
pod "ThingSmartBusinessExtensionKit"
end
设备固件信息
open class ThingUpgradeListInfo : NSObject {
open var devId: String
open var icon: String
open var name: String
open var upgradeList: [ThingSmartFirmwareUpgradeModel]
}
批量 OTA 管理类
open class ThingUpgradeListManager : NSObject {
...
}
查询家庭下需要进行 OTA 升级的设备及固件信息。
入参 | 类型 | 说明 |
---|---|---|
familyId | Int64 | 家庭 ID |
success | [ThingUpgradeListInfo] | 设备固件信息 |
failure | error | 错误信息 |
返回值:true
表示支持,false
表示不支持。
func getUpgradeDevices(
inFamily familyId: Int64,
success: @escaping ([ThingUpgradeListInfo]) -> Void,
failure: @escaping (Error) -> Void
)
更多信息,参考 Demo。
import UIKit
class BatchOtaVC: UITableViewController {
var home: ThingSmartHome
init(home: ThingSmartHome) {
self.home = home
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.prefersLargeTitles = false
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UIColor.white
self.navigationController?.navigationBar.standardAppearance = appearance;
self.navigationController?.navigationBar.scrollEdgeAppearance = self.navigationController?.navigationBar.standardAppearance
} else {
// Fallback on earlier versions
}
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.title = "batch ota"
self.loadData()
}
var infos: [ThingUpgradeListInfo] = []
var devices: [String: ThingSmartDevice] = [:]
var status: [String: String] = [:]
func loadData() {
SVProgressHUD.show()
ThingUpgradeListManager.sharedInstance().getUpgradeDevices(inFamily: self.home.homeId) { infos in
SVProgressHUD.dismiss()
self.infos = infos
infos.forEach { info in
let device = ThingSmartDevice(deviceId: info.devId)
device?.delegate = self
if (device != nil) {
self.devices.updateValue(device!, forKey: info.devId)
}
let upgradeInfo = ThingUpgradeInfo(firmwares: info.upgradeList)
if (upgradeInfo.matchUpgradeCondition == false) {
self.status.updateValue("can't grade", forKey: info.devId)
}else if (upgradeInfo.isUpgrading == false) {
self.status.updateValue("need upgrade", forKey: info.devId)
}else{
self.status.updateValue("upgrading", forKey: info.devId)
}
}
self.tableView.reloadData()
} failure: { error in
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "error")
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.infos.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .value1, reuseIdentifier: "cell")
let info = self.infos[indexPath.row]
cell.textLabel?.text = info.name
cell.detailTextLabel?.text = self.status[info.devId]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let info = self.infos[indexPath.row]
let upgradeInfo = ThingUpgradeInfo(firmwares: info.upgradeList)
if (upgradeInfo.matchUpgradeCondition == false) {return}
if (self.status[info.devId] != nil && self.status[info.devId]! == "upgrading") {return}
let device = self.devices[info.devId]
device?.startFirmwareUpgrade(info.upgradeList)
}
}
extension BatchOtaVC: ThingSmartDeviceDelegate {
func device(_ device: ThingSmartDevice, otaUpdateStatusChanged statusModel: ThingSmartFirmwareUpgradeStatusModel) {
if (statusModel.upgradeStatus == ThingSmartDeviceUpgradeStatusTimeout || statusModel.upgradeStatus == ThingSmartDeviceUpgradeStatusFailure) {
self.status.updateValue("fail", forKey: device.deviceModel.devId)
}else{
self.status.updateValue("upgrading", forKey: device.deviceModel.devId)
}
self.tableView.reloadData()
}
}
展示如何实现简单的批量 OTA 升级功能。
首先,简单实现一个界面。
界面初始化的时候,传入当前的家庭的 homeId
。
界面会展示一个 UITableView
,此时 UITableView
的分组数和行数都为 0
。另外,将会以 value1
的样式来创建 cell
。
import UIKit
class BatchOtaVC: UITableViewController {
var home: ThingSmartHome
init(home: ThingSmartHome) {
self.home = home
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.prefersLargeTitles = false
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UIColor.white
self.navigationController?.navigationBar.standardAppearance = appearance;
self.navigationController?.navigationBar.scrollEdgeAppearance = self.navigationController?.navigationBar.standardAppearance
} else {
// Fallback on earlier versions
}
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.title = "batch ota"
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .value1, reuseIdentifier: "cell")
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
接下来,开始加载当前家庭下需要升级的设备。实现一个 loadData
方法,在其中调用 ThingUpgradeListManager
的 getUpgradeDevices(inFamily:success:failure:)
方法。
import UIKit
class BatchOtaVC: UITableViewController {
override func viewDidLoad() {
...
self.loadData()
}
func loadData() {
SVProgressHUD.show()
ThingUpgradeListManager.sharedInstance().getUpgradeDevices(inFamily: self.home.homeId) { infos in
SVProgressHUD.dismiss()
} failure: { error in
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "error")
}
}
}
获取到当前家庭下需要 OTA 的设备的固件信息。用 infos
来存储需要 OTA 的设备的固件信息,同时根据 infos
来渲染 tableview
。
import UIKit
class BatchOtaVC: UITableViewController {
var infos: [ThingUpgradeListInfo] = []
func loadData() {
SVProgressHUD.show()
ThingUpgradeListManager.sharedInstance().getUpgradeDevices(inFamily: self.home.homeId) { infos in
SVProgressHUD.dismiss()
self.infos = infos
self.tableView.reloadData()
} failure: { error in
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "error")
}
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.infos.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .value1, reuseIdentifier: "cell")
let info = self.infos[indexPath.row]
cell.textLabel?.text = info.name
return cell
}
}
现在,已经展示出了需要 OTA 的设备列表。要对设备进行 OTA,需要用到 ThingSmartDevice
。因此,创建一个 devices
字典来存储这些设备,并监听设备的回调。
import UIKit
class BatchOtaVC: UITableViewController {
var devices: [String: ThingSmartDevice] = [:]
func loadData() {
SVProgressHUD.show()
ThingUpgradeListManager.sharedInstance().getUpgradeDevices(inFamily: self.home.homeId) { infos in
SVProgressHUD.dismiss()
self.infos = infos
infos.forEach { info in
let device = ThingSmartDevice(deviceId: info.devId)
device?.delegate = self
if (device != nil) {
self.devices.updateValue(device!, forKey: info.devId)
}
}
self.tableView.reloadData()
} failure: { error in
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "error")
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let info = self.infos[indexPath.row]
let device = self.devices[info.devId]
device?.startFirmwareUpgrade(info.upgradeList)
}
}
extension BatchOtaVC: ThingSmartDeviceDelegate {
func device(_ device: ThingSmartDevice, otaUpdateStatusChanged statusModel: ThingSmartFirmwareUpgradeStatusModel) {
}
}
好了,现在单击 tableview
上的设备就可以进行 OTA 了。但是并不是需要 OTA 的设备就可以进行升级,可能设备当前不满足升级条件,例如电量。也可能是因为设备当前正在升级中。因此,可以用一个 status
来维护这些状态。
import UIKit
class BatchOtaVC: UITableViewController {
var status: [String: String] = [:]
func loadData() {
SVProgressHUD.show()
ThingUpgradeListManager.sharedInstance().getUpgradeDevices(inFamily: self.home.homeId) { infos in
SVProgressHUD.dismiss()
self.infos = infos
infos.forEach { info in
...
let upgradeInfo = ThingUpgradeInfo(firmwares: info.upgradeList)
if (upgradeInfo.matchUpgradeCondition == false) {
self.status.updateValue("can't grade", forKey: info.devId)
}else if (upgradeInfo.isUpgrading == false) {
self.status.updateValue("need upgrade", forKey: info.devId)
}else{
self.status.updateValue("upgrading", forKey: info.devId)
}
}
self.tableView.reloadData()
} failure: { error in
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "error")
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.detailTextLabel?.text = self.status[info.devId]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
...
let upgradeInfo = ThingUpgradeInfo(firmwares: info.upgradeList)
if (upgradeInfo.matchUpgradeCondition == false) {return}
if (self.status[info.devId] != nil && self.status[info.devId]! == "upgrading") {return}
let device = self.devices[info.devId]
device?.startFirmwareUpgrade(info.upgradeList)
}
}
extension BatchOtaVC: ThingSmartDeviceDelegate {
func device(_ device: ThingSmartDevice, otaUpdateStatusChanged statusModel: ThingSmartFirmwareUpgradeStatusModel) {
if (statusModel.upgradeStatus == ThingSmartDeviceUpgradeStatusTimeout || statusModel.upgradeStatus == ThingSmartDeviceUpgradeStatusFailure) {
self.status.updateValue("fail", forKey: device.deviceModel.devId)
}else{
self.status.updateValue("upgrading", forKey: device.deviceModel.devId)
}
self.tableView.reloadData()
}
}
获取家庭下需升级设备的 OTA 信息所返回的数据并没有包含蓝牙本地的 OTA 状态。也就是说,如果您的蓝牙设备在进行 OTA 升级时状态已经变成 升级中 了,但是此时您调 ThingUpgradeListManager.getUpgradeDevices(inFamily:success:failure:)
接口会发现,返回的状态是 待升级。
因此,建议在蓝牙设备进行 OTA 升级的时候,不要关闭升级界面,以避免界面重入时状态不一致的问题。
更多信息,参考 Demo。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈