2024-11-25

iOS-OTA版本说明

OTASDKDemo的目的是做最简单的OTA集成Demo程序,让开发者能以最小的成本实现对我司OTASDK的整合。

请将Xcode版本升级到Xcode14以上。否则会出现找不到符号的错误。

SLB OTA参考的网址https://www.aligenie.com/doc/357554/iz1ttl

20220628更新1.1.1版本

1、支持多设备OTA,同一时间可以并行6个设备进行数据传输

2、优化使用体验,不再需要选择模式,会根据设备服务特性自动进行判断

3、优化升级成功率

4、优化错误码

5、简化SDK开发流程

按如下流程进行处理:

  • initOTA
  • startScan
  • selectFilePath
  • addDevices
  • tryStartOTA

App Store 1.1.2版本 针对重复升级模式,进行优化,没有涉及SDK上的修改

20220801 SDK 更新1.1.3版本 针对App已经连接设备的情况下,集成我司SDK,在不断开的情况下,直接传递蓝牙对象进行OTA。对手环项目,这是非常必要的优化。

奉加OTA开发文档

一、如何使用OTASDK.xcframework

1、导入头文件

#import <OTASDK/OTASDK.h>

2、初始化蓝牙中心管理器,一定要设置委托协议PHYBLEManagerDelegate。

self.bluetoothManager = [PHYBLEManager shareInstance];
self.bluetoothManager.delegate = self;

3、监听设备蓝牙开启或关闭

- (void)centerMessage:(NSString *)message code:(NSUInteger)code {
    
    if (code == BLENOTActive) {
        NSLog(@"%@",message);
        [self stopScanAction];
    }else if(code == BLEActive) {
        [self startScanAction];
    }
    
}

4、扫描设备。会将未设备蓝牙名的设备过滤掉,在开启扫描前,先判断是否已经在扫描中,避免重复扫描,节约资源。

if (!self.bluetoothManager.isScanning) {
   [self.bluetoothManager startScan];
}

扫描结果回调:

- (void)deviceFound:(NSArray *)devicesArray {
    
    self.showArray = [devicesArray mutableCopy];
    [self.tableView reloadData];
    
}

5、停止扫描

if (self.bluetoothManager.isScanning) {
    [self.bluetoothManager stopScan];
}

6、选择需要升级的设备,以数组形式设置。

[self.bluetoothManager addDevices:self.selectArray];

7、为设备选择升级文件,这个方法应该在添加设备之前。

[self.bluetoothManager selectFilePath:fileModel.fileAbsolutePath];

8、开始升级

[self.bluetoothManager tryStartOTA];

9、清空设备列表和文件数据,意味着OTA升级环境变量初始化,重新开始OTA前最好是执行这个方法重置一次。

[self.bluetoothManager initOTA];

10、进度信息,升级完成,升级异常等等,均通过如下回调

- (void)listenNotify:(CBPeripheral *)peripheral message:(NSString *)message code:(NSUInteger)code {
    self.selectArray = [self.bluetoothManager.deviceArray mutableCopy];
    
    [self.tableView reloadData];
}

iOS OTA代码详解

1、AppDelegate

合并项目时用不到。如下代码是其他文件打开接收升级文件,将升级文件从微信,QQ,钉钉等通信App下载后存入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发送请求的应用程序的 Bundle ID:%@\n\n文件的NSURL:%@", options[UIApplicationOpenURLOptionsSourceApplicationKey], url];
        NSLog(@"%@", str);
        
        if (self.window && url) {
            // 根据“其他应用” 用“本应用”打开,通过url,进入列表页
            [self pushDocListViewControllerWithUrl:url];
        }
    }
    return YES;
}

#pragma mark ApplicationDelegate Method
/** 根据“其他应用” 用“本应用”打开,通过url,进入列表页 */
- (void)pushDocListViewControllerWithUrl:(NSURL *)url {

}

2、SelectDeviceVC

实现扫描周边蓝牙设备,选择待升级设备的功能。

主要涉及如下代码

2.1、蓝牙初始化和设置委托

//蓝牙初始化
  self.bluetoothManager = [PHYBLEManager shareInstance];
  self.bluetoothManager.delegate = self;

执行self.bluetoothManager.delegate = self;时会将蓝牙中心回调指向OTASDK。

2.2、将OTA状态初始化

一般客户工程师无需进行这步,在SDK内部,每一次新的OTA开始时会自动执行。

[self.bluetoothManager initOTA];

SDK内部实现如下:

- (void)initOTA {
    [self.deviceArray removeAllObjects];
    myFilePath = nil;
    fileDetail = nil;
    isStartOTA = NO;
    mtusize = 0;
}

2.3、开始扫描设备

[self startScanAction];

扫描结果会在deviceFound回调方法中返回。返回结果是过滤掉空蓝牙名,根据信号强度排序的所有设备的数组。

- (void)deviceFound:(NSArray *)devicesArray

2.4、SDK对蓝牙是否开启的检测

如果检测到手机蓝牙已关闭,会通过如下回调中返回。这个部分一般用不到,客户工程师都会在项目启动时就进行检测。

可以参考代码中关于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、扫描时不会触发具体蓝牙设备的回调

为了兼容Swift,3个委托方法必须实现,但在扫描期间如下回调方法不会用到

- (void)listenNotify:(CBPeripheral *)peripheral message:(NSString *)message code:(NSUInteger)code {
    NSLog(@"%@ -- %@",peripheral.name, message);
}

2.6、将选择的设备传到SDK

使用如下语句将选择的设备传到SDK。至少选择一个设备。

 [self.bluetoothManager addDevices:self.selectArray];

在执行上述语句前,请确认2.1中的委托已经设置。因为在执行上述语句后,会自动连接数组中的第一个设备。如果没有设置委托,将接收不到相关的回调的信息。

3.OTAUpgradeVC

实现每个蓝牙设备的连接状态,传输升级文件进度,正常或异常情况等。SDK中支持同时对6个进行升级。

3.1、蓝牙初始化和设置委托

如果客户项目中有多类调用了BLEManager,则需要自己控制想让哪个VC接收delegate的回调方法。

 self.bluetoothManager = [PHYBLEManager shareInstance];
 self.bluetoothManager.delegate = self;

3.2、获取SDK中待升级设备

self.selectArray = [self.bluetoothManager.deviceArray mutableCopy];

待升级数组中的元素为PHYBLEModel对象,具体的定义如下:

@interface PHYBLEModel : NSObject

@property (nonatomic, strong) CBPeripheral *peripheral;   //系统蓝牙对象
@property (nonatomic, strong) NSDictionary *advertisementData;//广播数据
@property (nonatomic, strong) NSNumber     *RSSI;                   //信号强度
@property (nonatomic, strong) NSString     *realName;    //设备名称
@property (nonatomic, strong) NSString     *adverMacAddr; //MAC地址
@property (nonatomic, strong) NSDate       *lastUpdateDate; //最后一次扫描时间

@property (nonatomic, assign) NSInteger    OTAType;      //OTA类型:SLB或者SingleBank
@property (nonatomic, strong) NSString     *OTAMessage;  //显示的提示信息
@property (nonatomic, assign) int          disconnectTimes; //断开连接次数

@property (nonatomic, strong) SLBContext   *mSLBContext;  //SLB模式传输数据中的参数
@property (nonatomic, strong) SBHContext   *mSBHContext;  //SBH模式传输数据中的参数
@property (nonatomic, strong, nullable) NSTimer      *myTimer; //定时器
@property (nonatomic, strong) NSMutableArray *bufferArray;   //一组数据的缓存

@end

可以根据待升级设备数组中元素的参数自行判断设备的详细状态。

3.3、升级模式:单次模式和循环模式

循环模式是为了压测OTA的稳定性,一般开发者不用管,代码合并时也不要理会。

3.4、加密OTA:Security OTA模式

Security OTA目前只在SBH模式下实现了,不支持SLB。仅支持hexe16格式的升级文件,使用的客户较少,客户喜欢自研加密算法。

SLB加密OTA暂时没有开发计划。

如果不是加密模式,则项目中涉及到密钥的代码都可以不看。

3.5、总结:自定义功能的实现方法

self.bluetoothManager.deviceArray的结果就是实时的SDK中待升级设备的状态和各项参数。

第二种场景

假设项目中已经连接蓝牙设备,不想经过断开后再扫描、重连的耗时操作,如何进行OTA?

这个场景下只支持单个设备OTA升级的情况。

专门针对这种场景,基于第一个场景的代码逻辑,改编出了如下解决方案。

4、DemoVC

这个模式需要开发者,根据自己设备名修改代码。

打开App后,直接通过左上角的测试按钮,进入到测试页面。

首先在demo程序源码中,设置要升级设备的MAC地址或者UDID地址,模拟设备已经连接,然后修改项目中升级文件名称。

4.1、蓝牙初始化

假如客户使用的是CBCentralManager,将系统蓝牙的回调类指定为当前类。同时进行PHYBLEManager的初始化,但不要设置委托。

self.mCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
self.bluetoothManager = [PHYBLEManager shareInstance];

4.2、模拟设备已连接

模拟客户App中启动App立即连接设备的操作。

在Demo页面中按下开始按钮进行扫描,这里提供了两种方式,可以根据MAC地址或蓝牙名称,或者您可以自己根据广播信息及UUID等其他方式建立连接。

进入到DemoVC页面,打开蓝牙就会开始扫描,建立连接,发现服务和特性。

- (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(@"找到设备,进行连接!%@",self.mPeripheral);
        [self.mCentralManager connectPeripheral:self.mPeripheral options:nil];
    }else if(peripheral.name.length > 0){
        NSLog(@"%@",peripheral.name);
    }
    
}

4.3、已连接单个设备OTA

需要修改升级文件名。Demo

在设备已经连接的前提下,点击DemoVC页面中的开始按钮,执行如下代码,等待升级成功即可。

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];
  • 我们知道手机中只有一个蓝牙,所以这里采用将DemoVC中的蓝牙管理对象CBCentralManager传递到SDK中。传递之后接收不到CBCentralManager的委托方法,相当于蓝牙访问权限交给了OTASDK。
  • 接收来自OTASDK的回调方法,设置OTASDK的委托为当前类。
  • 设置升级文件,可以写死的项目中或者通过服务器下载。
  • 将要升级的设备传递到SDK中。SLB模式下MAC地址可以填空字符串@“”。

4.4、OTASDK回调方法

以获取自定义进度条的值作为例子,代码如下:

- (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中目前已经支持的事件

typedef NS_ENUM(NSInteger, OTAType) {
    None = 0,
    /*蓝牙状态*/
    BLENOTActive,           //未检测到蓝牙开启!
    BLEActive,              //成功检测到蓝牙开启!
    LastTaskNotEnd,         //上次升级任务还未完成!
    UnexpectedConnection,   //存在意料之外的BLE连接!
    ChangeFileFail,         //升级途中不能修改OTA文件!
    UnbelievableError,      //理论上不会触发的错误!
    OTAEnd,                 //本轮OTA结束
    RESCANStart,            //二次扫描开始
    RESCANDevice,           //二次扫描找到设备

    DeviceConnecting,       //连接中...
    DeviceConnectFail,      //设备建立连接失败!
    DeviceDisconnected,     //设备连接已经断开!
    
    ServicesDiscovering,    //连接成功,发现服务中...
    SLBServiceFound,        //SLB服务获取成功!发现特性中!
    SBHServiceFound,        //SBH服务获取成功,发现特性中!
    
    SLBOTAConfirm,          //特性确认,SLB升级模式!
    SBHAppConfirm,          //特性确认,SBH App模式!
    SBHOTAConfirm,          //特性确认,SBH OTA模式!
    
    SBHAppSecurity,         //安全模式下指令传输
    SLBDeviceReady,         //特性Enable成功,SLB设备已准备好!
    SBHOTADeviceReady,      //特性Enable成功,SBH OTA已准备好!
    
    ProgressCallBack,       //进度值返回
    OTADataOver,            //数据发送完毕,确认升级数据中...
    OTACheckFail,           //数据传输完成后,CRC校验失败!
    
    OTAComplete = 99,       //升级成功,可以主动断开或者超时断开!
    
    // 寻找下一个设备时,不需要再连接
    SBHAppOver = 100,       //SBH App模式结束,等待二次扫描
    
    // 无法进行OTA的错误类型
    OTAServiceNotFound,     //设备缺少OTA的蓝牙服务!
    OTAServiceConfuse,      //同时存在两种升级服务!
    CharacteristicError,    //特性异常!
    MTUConflict,            //不支持该设备:MTUSize不一致!
    MAXDisconnectedTime,    //达到最大连接异常断开次数
    NOMACAddress,
    
};

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容