iOS-OTA版本說明
OTASDKDemo的目的是做最簡單的OTA集成Demo程序吟温,讓開發(fā)者能以最小的成本實(shí)現(xiàn)對我司OTASDK的整合绞灼。
請將Xcode版本升級到Xcode14以上姿骏。否則會出現(xiàn)找不到符號的錯(cuò)誤。
SLB OTA參考的網(wǎng)址https://www.aligenie.com/doc/357554/iz1ttl
20220628更新1.1.1版本
1尺借、支持多設(shè)備OTA顶岸,同一時(shí)間可以并行6個(gè)設(shè)備進(jìn)行數(shù)據(jù)傳輸
2、優(yōu)化使用體驗(yàn)芍阎,不再需要選擇模式世曾,會根據(jù)設(shè)備服務(wù)特性自動進(jìn)行判斷
3、優(yōu)化升級成功率
4谴咸、優(yōu)化錯(cuò)誤碼
5轮听、簡化SDK開發(fā)流程
按如下流程進(jìn)行處理:
- initOTA
- startScan
- selectFilePath
- addDevices
- tryStartOTA
App Store 1.1.2版本 針對重復(fù)升級模式,進(jìn)行優(yōu)化岭佳,沒有涉及SDK上的修改
20220801 SDK 更新1.1.3版本 針對App已經(jīng)連接設(shè)備的情況下血巍,集成我司SDK,在不斷開的情況下珊随,直接傳遞藍(lán)牙對象進(jìn)行OTA述寡。對手環(huán)項(xiàng)目,這是非常必要的優(yōu)化叶洞。
奉加OTA開發(fā)文檔
一鲫凶、如何使用OTASDK.xcframework
1、導(dǎo)入頭文件
#import <OTASDK/OTASDK.h>
2衩辟、初始化藍(lán)牙中心管理器螟炫,一定要設(shè)置委托協(xié)議PHYBLEManagerDelegate。
self.bluetoothManager = [PHYBLEManager shareInstance];
self.bluetoothManager.delegate = self;
3艺晴、監(jiān)聽設(shè)備藍(lán)牙開啟或關(guān)閉
- (void)centerMessage:(NSString *)message code:(NSUInteger)code {
if (code == BLENOTActive) {
NSLog(@"%@",message);
[self stopScanAction];
}else if(code == BLEActive) {
[self startScanAction];
}
}
4昼钻、掃描設(shè)備。會將未設(shè)備藍(lán)牙名的設(shè)備過濾掉财饥,在開啟掃描前换吧,先判斷是否已經(jīng)在掃描中,避免重復(fù)掃描钥星,節(jié)約資源沾瓦。
if (!self.bluetoothManager.isScanning) {
[self.bluetoothManager startScan];
}
掃描結(jié)果回調(diào):
- (void)deviceFound:(NSArray *)devicesArray {
self.showArray = [devicesArray mutableCopy];
[self.tableView reloadData];
}
5、停止掃描
if (self.bluetoothManager.isScanning) {
[self.bluetoothManager stopScan];
}
6谦炒、選擇需要升級的設(shè)備贯莺,以數(shù)組形式設(shè)置。
[self.bluetoothManager addDevices:self.selectArray];
7宁改、為設(shè)備選擇升級文件缕探,這個(gè)方法應(yīng)該在添加設(shè)備
之前。
[self.bluetoothManager selectFilePath:fileModel.fileAbsolutePath];
8还蹲、開始升級
[self.bluetoothManager tryStartOTA];
9爹耗、清空設(shè)備列表和文件數(shù)據(jù)耙考,意味著OTA升級環(huán)境變量初始化,重新開始OTA前最好是執(zhí)行這個(gè)方法重置一次潭兽。
[self.bluetoothManager initOTA];
10倦始、進(jìn)度信息,升級完成山卦,升級異常等等鞋邑,均通過如下回調(diào)
- (void)listenNotify:(CBPeripheral *)peripheral message:(NSString *)message code:(NSUInteger)code {
self.selectArray = [self.bluetoothManager.deviceArray mutableCopy];
[self.tableView reloadData];
}
iOS OTA代碼詳解
1、AppDelegate
合并項(xiàng)目時(shí)用不到账蓉。如下代碼是其他文件打開
接收升級文件枚碗,將升級文件從微信,QQ铸本,釘釘?shù)韧ㄐ臕pp下載后存入iOS App儲存空間肮雨。
#pragma mark - ApplicationDelegate
- (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options {
if (options) {
NSString *str = [NSString stringWithFormat:@"\n發(fā)送請求的應(yīng)用程序的 Bundle ID:%@\n\n文件的NSURL:%@", options[UIApplicationOpenURLOptionsSourceApplicationKey], url];
NSLog(@"%@", str);
if (self.window && url) {
// 根據(jù)“其他應(yīng)用” 用“本應(yīng)用”打開,通過url归敬,進(jìn)入列表頁
[self pushDocListViewControllerWithUrl:url];
}
}
return YES;
}
#pragma mark ApplicationDelegate Method
/** 根據(jù)“其他應(yīng)用” 用“本應(yīng)用”打開酷含,通過url,進(jìn)入列表頁 */
- (void)pushDocListViewControllerWithUrl:(NSURL *)url {
}
2汪茧、SelectDeviceVC
實(shí)現(xiàn)掃描周邊藍(lán)牙設(shè)備椅亚,選擇待升級設(shè)備的功能。
主要涉及如下代碼
2.1舱污、藍(lán)牙初始化和設(shè)置委托
//藍(lán)牙初始化
self.bluetoothManager = [PHYBLEManager shareInstance];
self.bluetoothManager.delegate = self;
執(zhí)行self.bluetoothManager.delegate = self;
時(shí)會將藍(lán)牙中心回調(diào)指向OTASDK呀舔。
2.2、將OTA狀態(tài)初始化
一般客戶工程師無需進(jìn)行這步扩灯,在SDK內(nèi)部媚赖,每一次新的OTA開始時(shí)會自動執(zhí)行。
[self.bluetoothManager initOTA];
SDK內(nèi)部實(shí)現(xiàn)如下:
- (void)initOTA {
[self.deviceArray removeAllObjects];
myFilePath = nil;
fileDetail = nil;
isStartOTA = NO;
mtusize = 0;
}
2.3珠插、開始掃描設(shè)備
[self startScanAction];
掃描結(jié)果會在deviceFound回調(diào)方法中返回惧磺。返回結(jié)果是過濾掉空藍(lán)牙名,根據(jù)信號強(qiáng)度排序的所有設(shè)備的數(shù)組捻撑。
- (void)deviceFound:(NSArray *)devicesArray
2.4磨隘、SDK對藍(lán)牙是否開啟的檢測
如果檢測到手機(jī)藍(lán)牙已關(guān)閉,會通過如下回調(diào)中返回顾患。這個(gè)部分一般用不到番捂,客戶工程師都會在項(xiàng)目啟動時(shí)就進(jìn)行檢測。
可以參考代碼中關(guān)于OTAType枚舉值的使用方式
- (void)centerMessage:(NSString *)message code:(NSUInteger)code {
self.showTip.text = message;
if (code == BLENOTActive) {
NSLog(@"%@",message);
[self stopScanAction];
}else if(code == BLEActive) {
[self startScanAction];
}else {
[self showAlert:message];
}
}
2.5江解、掃描時(shí)不會觸發(fā)具體藍(lán)牙設(shè)備的回調(diào)
為了兼容Swift设预,3個(gè)委托方法必須實(shí)現(xiàn),但在掃描期間如下回調(diào)方法不會用到
- (void)listenNotify:(CBPeripheral *)peripheral message:(NSString *)message code:(NSUInteger)code {
NSLog(@"%@ -- %@",peripheral.name, message);
}
2.6犁河、將選擇的設(shè)備傳到SDK
使用如下語句將選擇的設(shè)備傳到SDK鳖枕。至少選擇一個(gè)設(shè)備魄梯。
[self.bluetoothManager addDevices:self.selectArray];
在執(zhí)行上述語句前,請確認(rèn)2.1中的委托已經(jīng)設(shè)置宾符。因?yàn)樵趫?zhí)行上述語句后画恰,會自動連接數(shù)組中的第一個(gè)設(shè)備。如果沒有設(shè)置委托吸奴,將接收不到相關(guān)的回調(diào)的信息。
3.OTAUpgradeVC
實(shí)現(xiàn)每個(gè)藍(lán)牙設(shè)備的連接狀態(tài)缠局,傳輸升級文件進(jìn)度则奥,正常或異常情況等狭园。SDK中支持同時(shí)對6個(gè)進(jìn)行升級读处。
3.1、藍(lán)牙初始化和設(shè)置委托
如果客戶項(xiàng)目中有多類調(diào)用了BLEManager唱矛,則需要自己控制想讓哪個(gè)VC接收delegate的回調(diào)方法罚舱。
self.bluetoothManager = [PHYBLEManager shareInstance];
self.bluetoothManager.delegate = self;
3.2、獲取SDK中待升級設(shè)備
self.selectArray = [self.bluetoothManager.deviceArray mutableCopy];
待升級數(shù)組中的元素為PHYBLEModel對象绎谦,具體的定義如下:
@interface PHYBLEModel : NSObject
@property (nonatomic, strong) CBPeripheral *peripheral; //系統(tǒng)藍(lán)牙對象
@property (nonatomic, strong) NSDictionary *advertisementData;//廣播數(shù)據(jù)
@property (nonatomic, strong) NSNumber *RSSI; //信號強(qiáng)度
@property (nonatomic, strong) NSString *realName; //設(shè)備名稱
@property (nonatomic, strong) NSString *adverMacAddr; //MAC地址
@property (nonatomic, strong) NSDate *lastUpdateDate; //最后一次掃描時(shí)間
@property (nonatomic, assign) NSInteger OTAType; //OTA類型:SLB或者SingleBank
@property (nonatomic, strong) NSString *OTAMessage; //顯示的提示信息
@property (nonatomic, assign) int disconnectTimes; //斷開連接次數(shù)
@property (nonatomic, strong) SLBContext *mSLBContext; //SLB模式傳輸數(shù)據(jù)中的參數(shù)
@property (nonatomic, strong) SBHContext *mSBHContext; //SBH模式傳輸數(shù)據(jù)中的參數(shù)
@property (nonatomic, strong, nullable) NSTimer *myTimer; //定時(shí)器
@property (nonatomic, strong) NSMutableArray *bufferArray; //一組數(shù)據(jù)的緩存
@end
可以根據(jù)待升級設(shè)備數(shù)組中元素的參數(shù)自行判斷設(shè)備的詳細(xì)狀態(tài)管闷。
3.3、升級模式:單次模式和循環(huán)模式
循環(huán)模式是為了壓測OTA的穩(wěn)定性窃肠,一般開發(fā)者不用管包个,代碼合并時(shí)也不要理會。
3.4冤留、加密OTA:Security OTA模式
Security OTA目前只在SBH模式下實(shí)現(xiàn)了碧囊,不支持SLB。僅支持hexe16格式的升級文件纤怒,使用的客戶較少糯而,客戶喜歡自研加密算法。
SLB加密OTA暫時(shí)沒有開發(fā)計(jì)劃泊窘。
如果不是加密模式熄驼,則項(xiàng)目中涉及到密鑰的代碼都可以不看。
3.5州既、總結(jié):自定義功能的實(shí)現(xiàn)方法
self.bluetoothManager.deviceArray
的結(jié)果就是實(shí)時(shí)的SDK中待升級設(shè)備的狀態(tài)和各項(xiàng)參數(shù)谜洽。
第二種場景
假設(shè)項(xiàng)目中已經(jīng)連接藍(lán)牙設(shè)備,不想經(jīng)過斷開后再掃描吴叶、重連的耗時(shí)操作阐虚,如何進(jìn)行OTA?
這個(gè)場景下只支持單個(gè)設(shè)備OTA升級的情況。
專門針對這種場景蚌卤,基于第一個(gè)場景的代碼邏輯实束,改編出了如下解決方案奥秆。
4、DemoVC
這個(gè)模式需要開發(fā)者咸灿,根據(jù)自己設(shè)備名修改代碼构订。
打開App后,直接通過左上角的測試按鈕避矢,進(jìn)入到測試頁面悼瘾。
首先在demo程序源碼中,設(shè)置要升級設(shè)備的MAC地址或者UDID地址审胸,模擬設(shè)備已經(jīng)連接亥宿,然后修改項(xiàng)目中升級文件名稱。
4.1砂沛、藍(lán)牙初始化
假如客戶使用的是CBCentralManager烫扼,將系統(tǒng)藍(lán)牙的回調(diào)類指定為當(dāng)前類。同時(shí)進(jìn)行PHYBLEManager的初始化碍庵,但不要設(shè)置委托映企。
self.mCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
self.bluetoothManager = [PHYBLEManager shareInstance];
4.2、模擬設(shè)備已連接
模擬客戶App中啟動App立即連接設(shè)備的操作静浴。
在Demo頁面中按下開始按鈕進(jìn)行掃描堰氓,這里提供了兩種方式,可以根據(jù)MAC地址或藍(lán)牙名稱苹享,或者您可以自己根據(jù)廣播信息及UUID等其他方式建立連接豆赏。
進(jìn)入到DemoVC頁面,打開藍(lán)牙就會開始掃描富稻,建立連接掷邦,發(fā)現(xiàn)服務(wù)和特性。
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSObject *value = [advertisementData objectForKey:@"kCBAdvDataManufacturerData"];
self.macString = [JCDataConvert getPeripheralMac:value];
self.mPeripheral = peripheral;
if ([self.macString isEqualToString:@"A2:62:22:00:00:19"] ||
[peripheral.name isEqualToString:@"BUMBLE- -22000019"]) {
[self.mCentralManager stopScan];
NSLog(@"找到設(shè)備,進(jìn)行連接椭赋!%@",self.mPeripheral);
[self.mCentralManager connectPeripheral:self.mPeripheral options:nil];
}else if(peripheral.name.length > 0){
NSLog(@"%@",peripheral.name);
}
}
4.3抚岗、已連接單個(gè)設(shè)備OTA
需要修改升級文件名。Demo
在設(shè)備已經(jīng)連接的前提下哪怔,點(diǎn)擊DemoVC頁面中的開始按鈕宣蔚,執(zhí)行如下代碼,等待升級成功即可认境。
self.bluetoothManager.myCentralManager = _mCentralManager;
self.bluetoothManager.delegate = self;
//----------- 升級文件獲取的方式 -------------
NSString *folderPath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/Inbox/"]];
NSString *fileName = @"simpleBlePeripheral(1)_phy6222.hex16";
NSString *FileURL = [folderPath stringByAppendingPathComponent:fileName];
[self.bluetoothManager selectFilePath:FileURL];
[self.bluetoothManager connectedDeviceOTA:self.mPeripheral mac:self.macString];
- 我們知道手機(jī)中只有一個(gè)藍(lán)牙胚委,所以這里采用將DemoVC中的藍(lán)牙管理對象CBCentralManager傳遞到SDK中。傳遞之后接收不到CBCentralManager的委托方法叉信,相當(dāng)于藍(lán)牙訪問權(quán)限交給了OTASDK亩冬。
- 接收來自O(shè)TASDK的回調(diào)方法,設(shè)置OTASDK的委托為當(dāng)前類。
- 設(shè)置升級文件硅急,可以寫死的項(xiàng)目中或者通過服務(wù)器下載覆享。
- 將要升級的設(shè)備傳遞到SDK中。SLB模式下MAC地址可以填空字符串@“”营袜。
4.4撒顿、OTASDK回調(diào)方法
以獲取自定義進(jìn)度條的值作為例子,代碼如下:
- (void)listenNotify:(CBPeripheral *)peripheral message:(NSString *)message code:(NSUInteger)code {
self.showLabel.text = message;
if(code == ProgressCallBack) {
float value = [message floatValue];
NSLog(@"Custom progress value: %.2f",value);
}
}
另外:OTASDK中目前已經(jīng)支持的事件
typedef NS_ENUM(NSInteger, OTAType) {
None = 0,
/*藍(lán)牙狀態(tài)*/
BLENOTActive, //未檢測到藍(lán)牙開啟!
BLEActive, //成功檢測到藍(lán)牙開啟!
LastTaskNotEnd, //上次升級任務(wù)還未完成荚板!
UnexpectedConnection, //存在意料之外的BLE連接凤壁!
ChangeFileFail, //升級途中不能修改OTA文件!
UnbelievableError, //理論上不會觸發(fā)的錯(cuò)誤跪另!
OTAEnd, //本輪OTA結(jié)束
RESCANStart, //二次掃描開始
RESCANDevice, //二次掃描找到設(shè)備
DeviceConnecting, //連接中...
DeviceConnectFail, //設(shè)備建立連接失斂驮!
DeviceDisconnected, //設(shè)備連接已經(jīng)斷開罚斗!
ServicesDiscovering, //連接成功,發(fā)現(xiàn)服務(wù)中...
SLBServiceFound, //SLB服務(wù)獲取成功宅楞!發(fā)現(xiàn)特性中针姿!
SBHServiceFound, //SBH服務(wù)獲取成功,發(fā)現(xiàn)特性中!
SLBOTAConfirm, //特性確認(rèn),SLB升級模式厌衙!
SBHAppConfirm, //特性確認(rèn),SBH App模式距淫!
SBHOTAConfirm, //特性確認(rèn),SBH OTA模式!
SBHAppSecurity, //安全模式下指令傳輸
SLBDeviceReady, //特性Enable成功婶希,SLB設(shè)備已準(zhǔn)備好榕暇!
SBHOTADeviceReady, //特性Enable成功,SBH OTA已準(zhǔn)備好喻杈!
ProgressCallBack, //進(jìn)度值返回
OTADataOver, //數(shù)據(jù)發(fā)送完畢彤枢,確認(rèn)升級數(shù)據(jù)中...
OTACheckFail, //數(shù)據(jù)傳輸完成后,CRC校驗(yàn)失斖彩巍缴啡!
OTAComplete = 99, //升級成功,可以主動斷開或者超時(shí)斷開瓷们!
// 尋找下一個(gè)設(shè)備時(shí)业栅,不需要再連接
SBHAppOver = 100, //SBH App模式結(jié)束,等待二次掃描
// 無法進(jìn)行OTA的錯(cuò)誤類型
OTAServiceNotFound, //設(shè)備缺少OTA的藍(lán)牙服務(wù)谬晕!
OTAServiceConfuse, //同時(shí)存在兩種升級服務(wù)碘裕!
CharacteristicError, //特性異常!
MTUConflict, //不支持該設(shè)備:MTUSize不一致!
MAXDisconnectedTime, //達(dá)到最大連接異常斷開次數(shù)
NOMACAddress,
};