固件升级

更新时间:2023-03-09 08:04:34

固件升级是指把新的固件写入芯片中,代替原有的固件的过程。随着市场变化、开发方案升级等原因,涂鸦会定期进行固件更新。同时,涂鸦会根据原厂芯片迭代等情况,对部分旧版本进行停用。另外,设备本身也可以进行功能更新迭代,从而升级固件。

升级流程

  1. 查询设备升级信息。
  2. 下发模组升级指令。
  3. 模组升级成功。
  4. 下发设备控制模组升级指令。
  5. 设备控制模组升级成功。

从 v3.35.5 开始,新增 PID 版本升级固件,新的开始升级接口支持蓝牙设备的固件升级,并且可以选择多个固件升级。

查询升级信息

使用查询设备升级信息接口,可以查询到 TuyaSmartFirmwareUpgradeModel 固件升级模型。其中:

  • upgradeMode 属性表示固件类别。
  • type 属性表示固件通道类型。
  • typeDesc 属性表示固件类型的描述。

固件类别

查询固件列表时,TuyaSmartFirmwareUpgradeModelupgradeMode 字段

  • 普通固件:字段值为 0。传统意义上的固件,用于升级设备内固件。

  • PID 版本升级固件:字段值为 1。新引入产品版本的概念,不同版本间的数据能在指定功能模块范围内(即产品 schema 配置、面板配置、多语言配置、快捷控制配置)进行隔离配置。

    需要使用新接口获取固件列表、发起升级。

固件通道类型

作为标识 普通固件 的固件通道,在查询固件列表时,TuyaSmartFirmwareUpgradeModeltype 字段为固件通道类型,可以通过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<TuyaSmartFirmwareUpgradeModel *> *firmwares))success failure:(nullable TYFailureError)failure;

// 废弃,仅 获取 普通固件
- (void)getFirmwareUpgradeInfo:(nullable void (^)(NSArray <TuyaSmartFirmwareUpgradeModel *> *upgradeModelList))success failure:(nullable TYFailureError)failure;

参数说明

参数 说明
success 成功回调,设备的固件升级信息列表
failure 失败回调

TuyaSmartFirmwareUpgradeModel 数据模型

字段 类型 说明
desc NSString 升级文案
type NSInteger 固件通道类型,普通固件使用
typeDesc NSString 固件通道描述
upgradeStatus NSInteger
  • 0:无新版本
  • 1:有新版本
  • 2:在升级中
  • 5:等待设备唤醒
version NSString 新版本使用的固件版本
currentVersion NSString 当前的固件版本
devType NSInteger
  • 0:普通设备
  • 1:低功耗类型设备
upgradeType NSInteger
  • 0:App 提醒升级
  • 2:App 强制升级
  • 3:检测升级
url NSString 蓝牙设备的升级固件包下载 URL
fileSize NSString 固件包的大小,单位为字节 (byte)
md5 NSString 固件的 MD5
controlType BOOL
  • YES:升级中可控制
  • NO:升级中不可控制
waitingDesc NSString 固件等待设备唤醒的文案
upgradingDesc NSString 固件升级中的提示文案
canUpgrade NSNumber
  • nil: 无前置校验规则,可直接升级
  • 0: 有前置校验,不可升级,建议展示 remind 文案
  • 1: 有前置校验,可以升级
remind NSString 前置校验规则未通过的提示文案
upgradeMode TuyaSmartDeviceUpgradeMode 固件类别,v3.35.5 开始支持
  • 0: 普通固件
  • 1: PID 版本升级固件

示例代码

Objc:

- (void)getFirmwareUpgradeInfo {
	// self.device = [TuyaSmartDevice deviceWithDeviceId:@"your_device_id"];

	[self.device checkFirmwareUpgrade:^(NSArray<TuyaSmartFirmwareUpgradeModel *> *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 (^)(TuyaSmartFirmwareUpgradeStatusModel *status))success failure:(nullable TYFailureError)failure

参数说明

参数 说明
success 成功回调,升级状态模型
failure 失败回调,设备没有在升级 或 查询失败

TuyaSmartFirmwareUpgradeStatusModel 数据模型

字段 类型 说明
upgradeStatus TuyaSmartDeviceUpgradeStatus 升级状态枚举:
  • 2:在升级中
  • 3:升级成功
  • 4:升级失败
  • 5:等待设备唤醒
  • 6:设备已下载固件
  • 7:升级超时
  • 100:App 正在准备中(比如:正在连接蓝牙设备、App 正在下载固件包)
statusText NSString 状态描述
statusTitle NSString 状态标题
progress NSInteger 进度,部分情况下,参数值可能小于 0,请忽略此种小于 0 的进度
type NSInteger 固件通道类型,在确认升级时需要使用到
upgradeMode TuyaSmartDeviceUpgradeMode
  • 0:普通固件
  • 1:PID 版本升级,v3.35.5 开始支持
error NSError 失败信息

示例代码

Objc:

- (void)getFirmwareUpgradeInfo {
	// self.device = [TuyaSmartDevice deviceWithDeviceId:@"your_device_id"];

	[self.device getFirmwareUpgradingStatus:^(TuyaSmartFirmwareUpgradeStatusModel *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 动态网关 等设备的升级
// 同一设备的多个固件可以依次升级
- (void)startFirmwareUpgrade:(NSArray<TuyaSmartFirmwareUpgradeModel *> *)firmwares
  
// 废弃,推荐使用 `- startFirmwareUpgrade:` 发起升级
// 仅支持 普通固件,仅支持有 Wi-Fi 能力的设备 以及 Zigbee 子设备,无法支持单点蓝牙设备
// 仅能发起单个固件升级
// `type`:需要升级的类型,从设备升级信息接口 `getFirmwareUpgradeInfo` 获取
- (void)upgradeFirmware:(NSInteger)type success:(nullable TYSuccessHandler)success failure:(nullable TYFailureError)failure;

参数说明

  • -startFirmwareUpgrade: 接口参数说明
参数 说明
firmwares 从设备升级信息接口 getFirmwareUpgradeInfo 获取的固件列表
success 成功回调
failure 失败回调
  • -upgradeFirmware:success:failure: 接口参数说明
参数 说明
type type: 需要升级的类型,从设备升级信息接口 getFirmwareUpgradeInfo 获取
success 成功回调
failure 失败回调
  1. 通过设备升级信息接口 getFirmwareUpgradeInfo 获取的信息列表中会包含下列状态信息:

    • 无新版本 (upgradeStatus: 0)
    • 有新版本 (upgradeStatus: 1)
    • 在升级中 (upgradeStatus: 2)
    • 等待设备唤醒 (upgradeStatus: 5)

    上述状态信息用于展示升级相关状态。仅 有新版本 (upgradeStatus: 1) 状态时,可以发起升级。请在使用做好相关过滤和状态展示。

  2. 部分设备有前置校验限制。通过 getFirmwareUpgradeInfo 获取信息列表,采用其中任何一个升级信息模型 TuyaSmartFirmwareUpgradeModel 对象中的 canUpgrade 进行判断。

    判断说明 判断依据
    无需前置校验,可以升级 canUpgrade == nil
    有前置校验,且校验未通过,无法升级 canUpgrade != nil && canUpgrade.integerValue == 0
    有前置校验,且校验通过,可以升级 canUpgrade != nil && canUpgrade.integerValue == 1

    若有前置校验,且校验未通过,无法升级的,可以通过 remind 获取不可升级的说明文案。

示例代码

Objc:

- (void)upgradeFirmwareNew {
	// self.device = [TuyaSmartDevice deviceWithDeviceId:@"your_device_id"];
	
	// `firmwares`:从获取设备升级信息接口 `getFirmwareUpgradeInfo` 返回的固件列表
  // 注意,根据上述注意事项过滤掉不符合规则的固件
	[self.device startFirmwareUpgrade:firmwares];
}

Swift:

func upgradeFirmware() {
	  // `firmwares`:从获取设备升级信息接口 `getFirmwareUpgradeInfo` 返回的固件列表
	  // 注意,根据上述注意事项过滤掉不符合规则的固件
    device?.startFirmwareUpgrade(firmwares);
}

继续升级

目前仅支持在升级中收到进度回调时,error.codeTYOTAErrorCodeSignalStrengthNotSatisfy 的场景。

在升级 Wi-Fi 和双模类设备时,为保证升级通畅,通常会设置一个最低的信号强度。当发起升级时,会检查设备的信号强度是否符合。不符合,则会回调进度状态 error.code = TYOTAErrorCodeSignalStrengthNotSatisfy。此时,可以通过 UI 交互,让用户做选择。例如,弹窗提示:“设备信号弱,升级可能失败,是否继续升级?”


接口说明

- (void)confirmWarningUpgradeTask:(BOOL)isContinue;

参数说明

参数 说明
isContinue 是否继续升级

仅通过 -startFirmwareUpgrade: 发起的升级,才有此流程。

示例代码

Objc:

- (void)continueFirmware {
	// isContinue 由用户选择是否继续
	[self.device confirmWarningUpgradeTask:isContinue];
}

Swift:

func continueFirmware() {
    // isContinue 由用户选择是否继续
    device?.confirmWarningUpgradeTask(isContinue)
}

取消升级

目前仅支持低功耗类型的设备。此类设备在发起升级后,可能处于待唤醒状态(upgradeStatus == 5)。通过此方法,可以取消待唤醒的升级任务。


接口说明

// 目前仅支持取消低功耗类型的设备
- (void)cancelFirmwareUpgrade:(TYSuccessHandler)success
                      failure:(nullable TYFailureError)failure;

// 方法废弃,推荐使用 `-cancelFirmwareUpgrade:failure:` 
// `type`:从设备升级信息接口 `getFirmwareUpgradeInfo` 获取
- (void)cancelUpgradeFirmware:(NSInteger)type success:(nullable TYSuccessHandler)success failure:(nullable TYFailureError)failure;

参数说明

参数 说明
success 成功回调
failure 失败回调

取消待唤醒的升级,仅适用于 upgradeStatus5(等待设备唤醒)的设备。

示例代码

Objc:

- (void)cancelFirmware {
	// self.device = [TuyaSmartDevice deviceWithDeviceId:@"your_device_id"];
	// `type`:之前通过获取设备升级信息接口 `getFirmwareUpgradeInfo` 返回的固件类型
	// TuyaSmartFirmwareUpgradeModel - type
    // 仅适用于 `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: 回调。此回调包含 状态变化、进度更新、失败原因。其他废弃回调方法,也依然会回调。为了防止重复的回调监听,建议将相关逻辑迁移至此回调。

示例代码

Objc:

- (void)device:(TuyaSmartDevice *)device otaUpdateStatusChanged:(TuyaSmartFirmwareUpgradeStatusModel *)statusModel {
		// 固件升级状态和升级进度回调。
		// 推荐与 `-startFirmwareUpgrade:` 配套使用
}

- (void)device:(TuyaSmartDevice *)device firmwareUpgradeStatusModel:(TuyaSmartFirmwareUpgradeStatusModel *)upgradeStatusModel {
    // 固件升级状态回调。
    // 推荐与 `-upgradeFirmware:success:failure:` 配套使用
}

- (void)deviceFirmwareUpgradeSuccess:(TuyaSmartDevice *)device type:(NSInteger)type {
    // 固件升级成功。方法废弃,推荐使用 `- device:firmwareUpgradeStatusModel:`
}

- (void)deviceFirmwareUpgradeFailure:(TuyaSmartDevice *)device type:(NSInteger)type {
    // 固件升级失败。方法废弃,推荐使用 `- device:firmwareUpgradeStatusModel:`
}

- (void)device:(TuyaSmartDevice *)device firmwareUpgradeProgress:(NSInteger)type progress:(double)progress {
    // 固件升级的进度。
    // 推荐与 `-upgradeFirmware:success:failure:` 配套使用
}

Swift:

func device(_ device: TuyaSmartDevice, firmwareUpgradeStatusModel upgradeStatusModel: TuyaSmartFirmwareUpgradeStatusModel) {
    //设备升级状态变更
}

func deviceFirmwareUpgradeSuccess(_ device: TuyaSmartDevice!, type: Int) {
    //固件升级成功,即将弃用,推荐使用 `device(_:, firmwareUpgradeStatusModel:)`
}

func deviceFirmwareUpgradeFailure(_ device: TuyaSmartDevice!, type: Int) {
    //固件升级失败,即将弃用,推荐使用 `device(_:, firmwareUpgradeStatusModel:)`
}

func device(_ device: TuyaSmartDevice!, firmwareUpgradeProgress type: Int, progress: Double) {
    //固件升级的进度
}

自动保持最新版本

部分设备支持自动保持最新版本。通过 TuyaSmartDeviceModel - supportAuto 来判断设备是否支持该功能。

接口说明

// 获取开关状态
- (void)getAutoUpgradeSwitchInfoWithSuccess:(nullable TYSuccessID)success
                                    failure:(nullable TYFailureError)failure;

// 保存开关状态
- (void)saveUpgradeInfoWithSwitchValue:(NSInteger)switchValue
                               success:(nullable TYSuccessHandler)success
                               failure:(nullable TYFailureError)failure;

参数说明

参数 说明
switchValue 功能状态:
  • 0:关闭
  • 1:开启
success 成功回调
failure 失败回调

示例代码

Objc:

- (void)getAutoUpgradeSwitchInfo {
    // self.device = [TuyaSmartDevice deviceWithDeviceId:@"your_device_id"];
		// 注意需先通过 `TuyaSmartDeviceModel - 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 = [TuyaSmartDevice deviceWithDeviceId:@"your_device_id"];
    // 注意,需先通过 `TuyaSmartDeviceModel - 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() {
    // 注意,需先通过 `TuyaSmartDeviceModel - 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() {
    // 注意,需先通过 `TuyaSmartDeviceModel - 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)")
        }
    })
}

错误码

TuyaSmartFirmwareUpgradeStatusModel 中的 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 可升级固件列表接口请求失败
5099 通用错误码