iOS 藍(lán)牙開(kāi)發(fā)(固件升級(jí)&空中升級(jí))

最近幾個(gè)月都在做藍(lán)牙的項(xiàng)目,趁現(xiàn)在有空蝌戒,就把在藍(lán)牙開(kāi)發(fā)過(guò)程中的心得和踩過(guò)的坑給記錄下來(lái)设凹,分享給大家贸街,避免大家在藍(lán)牙開(kāi)發(fā)過(guò)程中能避免踩相同的坑。

本文是記錄的藍(lán)牙開(kāi)發(fā)系列第二篇狸相,想看第一篇關(guān)于藍(lán)牙開(kāi)發(fā)的使用請(qǐng)看這里

iOS 藍(lán)牙開(kāi)發(fā)(框架集成和數(shù)據(jù)交互)

正文:

概念:藍(lán)牙固件升級(jí)也叫空中升級(jí)薛匪,英文OTA,指在線(xiàn)下載好更新固件卷哩,在把固件文件發(fā)送到藍(lán)牙外設(shè)進(jìn)行升級(jí)蛋辈,類(lèi)似我們的手機(jī)系統(tǒng)更新。一般固件都是zip類(lèi)型的壓縮文件将谊,解壓后會(huì)有三個(gè)文件:

image.png

工具:使用開(kāi)源的第三方升級(jí)庫(kù)可以很方便地為藍(lán)牙外設(shè)進(jìn)行升級(jí)冷溶,這個(gè)庫(kù)有Android和iOS兩個(gè)版本:

IOS-Pods-DFU-Library

Android-DFU-Library

需要注意的是iOS是swift版本,如果你的項(xiàng)目是OC實(shí)現(xiàn)的尊浓,集成會(huì)有點(diǎn)麻煩,這里推薦用CocoaPod導(dǎo)入逞频,需要注意的是要在Podfile文件添加use_frameworks!
集成后添加swift橋接文件,為了省事栋齿,強(qiáng)烈建議在導(dǎo)入升級(jí)庫(kù)之前創(chuàng)建一個(gè)swift文件苗胀,Xcode會(huì)在你第一次創(chuàng)建swift文件時(shí)自動(dòng)詢(xún)問(wèn)你是否創(chuàng)建橋接文件,只要點(diǎn)擊“是”就完事了瓦堵。
這時(shí)候你會(huì)發(fā)現(xiàn)Xcode自動(dòng)創(chuàng)建一個(gè).h文件基协,文件名為
"你的項(xiàng)目名-Bridging-Header.h"

接下來(lái)在橋接文件里import你在oc類(lèi)需要用到的swift文件即可


image.png

使用方法,第一步,現(xiàn)在服務(wù)器下載好固件菇用,存入本地

    NSURL *url = [NSURL URLWithString:@"https://**********"];
    AFHTTPSessionManager *mange = [AFHTTPSessionManager manager];
        [[mange downloadTaskWithRequest:[NSURLRequest requestWithURL:url] progress:^(NSProgress * _Nonnull downloadProgress) {
            NSString *progress = [NSString stringWithFormat:@"%.0f%%",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount *100];

            dispatch_async(dispatch_get_main_queue(), ^{
                self.hud.labelText = NSStringFormat(@"下載進(jìn)度...%@",progress);
                self.hud.progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount;
            });


        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

            NSURL *downloadURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
            return [downloadURL URLByAppendingPathComponent:@"zipFile.zip"];

        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
            
            //藍(lán)牙升級(jí)
            [self uploadFileToBlueDevice:filePath];

        }] resume];
        
    }];

第二步澜驮,執(zhí)行藍(lán)牙升級(jí)

/**
 執(zhí)行升級(jí)文件發(fā)送到固件操作
 */
- (void)uploadFileToBlueDevice:(NSURL *)filePath{

    CBPeripheral *peripheral = [AYBlueHelp shareBlue].peripheral;

    DFUFirmware *selectedFirmware = [[DFUFirmware alloc] initWithUrlToZipFile:filePath];
 
    DFUServiceInitiator *initiator = [[DFUServiceInitiator alloc] initWithCentralManager: self.manage target:peripheral];
    [initiator withFirmware:selectedFirmware];
    initiator.delegate = self; // - to be informed about current state and errors
    initiator.logger = self;
    initiator.progressDelegate = self;
    [initiator start];
}

最后一步,遵守協(xié)議惋鸥,實(shí)現(xiàn)代理方法杂穷,監(jiān)聽(tīng)升級(jí)狀態(tài)


#pragma mark - LoggerDelegate
- (void)logWith:(enum LogLevel)level message:(NSString *)message{
    DLog(@"logWith---------level = %d,-------message,%@",level,message);
}
#pragma mark - DFUServiceDelegate


#pragma mark - DFUProgressDelegate

- (void)dfuProgressDidChangeFor:(NSInteger)part outOf:(NSInteger)totalParts to:(NSInteger)progress currentSpeedBytesPerSecond:(double)currentSpeedBytesPerSecond avgSpeedBytesPerSecond:(double)avgSpeedBytesPerSecond{
    
    self.hud.labelText = NSStringFormat(@"升級(jí)中...%zd %%",progress);
    self.hud.progress = progress * 0.01;
 
}

- (void)dfuStateDidChangeTo:(enum DFUState)state{
    DLog(@"dfuStateDidChangeTo-----------state = %d",state);
    
    if (state == 6) {
        [self.hud hide:YES];
        [MBProgressHUD wj_showSuccess:@"升級(jí)成功!"];

        //重新連接
        CBPeripheral *peripheral = [AYBlueHelp shareBlue].peripheral;
        [self.manage cancelPeripheralConnection:peripheral];
        
        self.manage = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
        [AYBlueHelp shareBlue].manage = self.manage;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self.manage scanForPeripheralsWithServices:nil options:nil];
        });

    }
}
- (void)dfuError:(enum DFUError)error didOccurWithMessage:(NSString *)message{
//    DLog(@"dfuError-----------error = %d,-------------message = %@",error,message);
    [self.hud hide:YES];
    [MBProgressHUD wj_showError:message];
}

這里三個(gè)坑非常有必要重點(diǎn)強(qiáng)調(diào)一下:
第一個(gè)坑:
服務(wù)器存放的固件名字為01&02&20180501,如果你把這個(gè)名字作為你的文件名存放在本地你會(huì)發(fā)現(xiàn)文件永遠(yuǎn)都是不對(duì)的卦绣,這個(gè)坑我前后弄了2個(gè)小時(shí)才發(fā)現(xiàn)原來(lái)文件名包含“&”特殊字符耐量,需要進(jìn)行轉(zhuǎn)義,這里建議直接以zipFile.zip等自定義的名字命名即可滤港±妊眩坑死了···**
第二個(gè)坑:
前面我們把固件下載后存在本地,本來(lái)以為下次再進(jìn)行下載的時(shí)候以相同的路徑和文件名存放會(huì)覆蓋掉前面的文件蜗搔,這樣每次下載下來(lái)的固件都是最新的劲藐,然而事實(shí)上并不會(huì),沙盒里還是你上一次的文件樟凄,需要我們手動(dòng)舊文件刪除再存新文件聘芜!
第三個(gè)坑:
我們進(jìn)行藍(lán)牙升級(jí)后,流程是要把固件重啟后再次自動(dòng)連接缝龄。因?yàn)槲覀兊挠布こ處煾嬖V我只要在升級(jí)前發(fā)送個(gè)協(xié)議命令汰现,升級(jí)后設(shè)備會(huì)自動(dòng)重啟挂谍,我只需要做好自動(dòng)連接就可以了。問(wèn)題就在于貌似是重新連接成功了瞎饲,設(shè)備也顯示已連接狀態(tài)口叙,手機(jī)也顯示已連接,但是接下來(lái)卻一直收不到藍(lán)牙數(shù)據(jù)嗅战,也無(wú)法發(fā)送藍(lán)牙數(shù)據(jù)交互妄田,一開(kāi)始是手動(dòng)先斷開(kāi)連接,再重新掃描驮捍,再連接疟呐。然而發(fā)現(xiàn)執(zhí)行斷開(kāi)連接:[self.manage cancelPeripheralConnection:self.peripheral];并不會(huì)執(zhí)行didDisconnectPeripheral代理方法,重新掃描也不會(huì)收到廣播數(shù)據(jù)...
最后分析有可能是升級(jí)完畢后我們的藍(lán)牙管理類(lèi)centerManage可能已經(jīng)失效或者被銷(xiāo)毀东且?因此嘗試重新創(chuàng)建启具,再進(jìn)行掃描操作,問(wèn)題解決I河尽B撤搿!

 self.manage = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
   
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self.manage scanForPeripheralsWithServices:nil options:nil];
        });

到此為止色查,有關(guān)藍(lán)牙升級(jí)的操作已經(jīng)寫(xiě)完了薯演,下一篇,我會(huì)總結(jié)一下在藍(lán)牙開(kāi)發(fā)過(guò)程中遇到的一些坑??

喜歡的點(diǎn)個(gè)紅心秧了,有什么問(wèn)題歡迎評(píng)論區(qū)討論~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涣仿,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子示惊,更是在濱河造成了極大的恐慌,老刑警劉巖愉镰,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件米罚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡丈探,警方通過(guò)查閱死者的電腦和手機(jī)录择,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)碗降,“玉大人隘竭,你說(shuō)我怎么就攤上這事∷显ǎ” “怎么了动看?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)爪幻。 經(jīng)常有香客問(wèn)我菱皆,道長(zhǎng)须误,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任仇轻,我火速辦了婚禮京痢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篷店。我一直安慰自己祭椰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布疲陕。 她就那樣靜靜地躺著方淤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸭轮。 梳的紋絲不亂的頭發(fā)上臣淤,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音窃爷,去河邊找鬼邑蒋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛按厘,可吹牛的內(nèi)容都是我干的医吊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼逮京,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼卿堂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起懒棉,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤草描,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后策严,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體穗慕,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年妻导,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逛绵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倔韭,死狀恐怖术浪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寿酌,我是刑警寧澤胰苏,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站份名,受9級(jí)特大地震影響碟联,放射性物質(zhì)發(fā)生泄漏妓美。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一鲤孵、第九天 我趴在偏房一處隱蔽的房頂上張望壶栋。 院中可真熱鬧,春花似錦普监、人聲如沸贵试。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)毙玻。三九已至,卻和暖如春廊散,著一層夾襖步出監(jiān)牢的瞬間桑滩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工允睹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留运准,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓缭受,卻偏偏與公主長(zhǎng)得像胁澳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子米者,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 1韭畸、通過(guò)CocoaPods安裝項(xiàng)目名稱(chēng)項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_x閱讀 15,968評(píng)論 3 119
  • 就像做了件微不足道的事情,西門(mén)殺繼續(xù)向東蔓搞,目光冰冷胰丁,腳步堅(jiān)定。 但在松樹(shù)下喂分,已經(jīng)死的不能再死隘马,卻還站立的穩(wěn)...
    超大白丁閱讀 141評(píng)論 0 0
  • 曾經(jīng)做過(guò)調(diào)查:“如果有足夠足夠多的錢(qián),你會(huì)去干什么蜒车?” 答案出奇的相似:浪跡天涯的旅行讳嘱。天吶!D鹄ⅰAぬ丁!你們有那么多...
    木子Angela閱讀 295評(píng)論 0 1
  • 本項(xiàng)目來(lái)自菜鳥(niǎo)窩嬉挡,有興趣者點(diǎn)擊http://www.cniao5.com/course/ 項(xiàng)目已經(jīng)做完钝鸽,https...
    小莊bb閱讀 1,883評(píng)論 0 1
  • 今天跟各位小伙伴分享一個(gè)小技巧——如何設(shè)置簡(jiǎn)書(shū)封面圖汇恤。 如果你和我一樣也愛(ài)在簡(jiǎn)書(shū)寫(xiě)點(diǎn)東西,那這個(gè)小技巧你一定會(huì)需要...
    違例閱讀 7,657評(píng)論 50 59