iOS藍牙空中升級(固件升級)

空中升級又叫固件升級,指你手機從服務(wù)器下載下來的包或者數(shù)據(jù)艇纺,通過藍牙傳輸給你的外設(shè)升級固件怎静。如果你能把藍牙的基礎(chǔ)搞懂,其實也并不是很難黔衡,我在這里只不過提供一下思路消约。

空中升級略難的地方在于數(shù)據(jù)處理和交互,尤其要以怎樣簡單完整的代碼來實現(xiàn)數(shù)據(jù)的讀寫是重點员帮,這就需要你和硬件工程師的交流和你自己的邏輯思維了或粮。

在上代碼以前,說一下有關(guān)藍牙的傳輸速度的捞高,因為我開發(fā)中碰到較大數(shù)據(jù)的傳輸氯材,著實害我費了很多腦筋渣锦。
藍牙數(shù)據(jù)傳輸中有連接延遲。其是為了低功耗考慮氢哮,允許從機在跳頻過程中不理會主機的跳頻指令袋毙,繼續(xù)睡眠一段時間。而主機不能因為從機睡眠而認為其斷開連接了冗尤。其是1.25毫秒一個單位听盖。明顯,這個數(shù)值越小裂七,傳輸速度也高皆看。
藍牙BLE協(xié)議規(guī)定連接參數(shù)最小是5,即7.25毫秒背零;而Android手機規(guī)定連接參數(shù)最小是8腰吟,即10毫秒。iOS規(guī)定是16徙瓶,即20毫秒毛雇。
連接參數(shù)完全由主機決定,但從機可以發(fā)出更新參數(shù)申請侦镇,主機可以接受也可以拒絕灵疮。Android手機一部接受,而ios比較嚴格壳繁,拒絕的概率比較高震捣。
一般場景,連接參數(shù)設(shè)置16氮趋,即20毫秒伍派,一般的傳輸速率是50* 20 = 1000字節(jié)/每秒江耀。如果每個連接事件傳輸更多的包剩胁,可以獲得更高的傳輸速率。
但是以上這種方法并不能真正解決傳輸?shù)乃俣瓤炻楣敹嘁簿拖嗖?倍或者3倍昵观。最好的方法就是在與app每次給藍牙發(fā)送的包數(shù),通暢可能考慮到數(shù)據(jù)不丟失舌稀,都是一包一包的發(fā)送啊犬,但是在空中升級這里不得已包數(shù)必須要多一點,比如一次發(fā)送十包壁查,具體還是看你們硬件那邊怎么寫藍牙協(xié)議了觉至。

我下面的demo是這樣的一個過程:
1.發(fā)送給外設(shè)指令,我要空中升級
->2.外設(shè)給我回OK之后我發(fā)送一個隨機數(shù)(自定義了一種隨機算法)睡腿,驗證開始固件升級
->3.判斷隨機數(shù)無誤语御,準備發(fā)送打包好的數(shù)據(jù)
->4.真正發(fā)送打包好的數(shù)據(jù)(每次發(fā)送10包峻贮,一包20個字節(jié)),這里會重復(fù)N多次应闯,看你的原數(shù)據(jù)包有多大纤控;每次接到我發(fā)的包后,外設(shè)都會給我會OK否碉纺,我收到OK后才會發(fā)一下個數(shù)據(jù)包
->5.告訴外設(shè)我數(shù)據(jù)發(fā)送完畢船万,并發(fā)送一段指令(包括本次空中升級數(shù)據(jù)包的大小,還有加密參數(shù)什么的)
->6.外設(shè)給我回OK無誤后骨田,才算真正升級完成

//更新特征的value時調(diào)用
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error) {
        return;
    }
    //找到已經(jīng)訂閱的串口耿导,輸出看結(jié)果
   if ([[characteristic.UUID UUIDString] isEqualToString:@"6E400003-B5A3-F393-E0A9-E50E24DCCA9E"]) {
       NSLog(@"返回的結(jié)果是 = %@",characteristic.value);
       
       [_dataArray addObject:characteristic.value];
       
       NSInteger arrayCount = _dataArray.count;
       //藍牙每次都會回三條數(shù)據(jù)
       if (arrayCount%3 == 0) {
           //返回的頭
           NSString *str=[[NSString alloc]initWithFormat:@"%@",_dataArray[arrayCount-3]];

           /*第一種大情況
            1.發(fā)送固件升級指令
            2.發(fā)送隨機數(shù)
            3.驗證隨機數(shù)是否正確
            */
           if ([str isEqualToString:@"<ab100000 00000000>"]) {
               
               NSData * data2 = _dataArray[arrayCount-1];
               NSString * string3 = [NSString stringWithFormat:@"%@",_dataArray[arrayCount-1]];

               //keyHead
               NSData * keyHead = [_dataArray[arrayCount-1] subdataWithRange:NSMakeRange(2, 1)];
               NSString * keyHeadStr = [NSString stringWithFormat:@"%@",keyHead];
               NSData * randomData1;
               NSData * randomData2;
               //隨機數(shù)
               if (data2.length == 7 ) {
                   randomData1 = [_dataArray[arrayCount-1] subdataWithRange:NSMakeRange(5, 1)];
                   randomData2 = [_dataArray[arrayCount-1] subdataWithRange:NSMakeRange(6, 1)];
               }
               
               //發(fā)起固件升級之后回的
               if ([string3 isEqualToString:@"<01008204 00010000 00>"]) {
                   //寫入隨機數(shù)
                   [self.peripherale writeValue:self.randomData forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                   NSLog(@"寫入的隨機數(shù) %@",self.randomData);
               }
               
               //寫入隨機數(shù)之后回的
               if ([randomData1 isEqualToData:[_calculateRandom subdataWithRange:NSMakeRange(13, 1)]] && [randomData2 isEqualToData:[_calculateRandom subdataWithRange:NSMakeRange(14, 1)]] && [keyHeadStr isEqualToString:@"<06>"]){
                   
                   //隨機數(shù)驗證成功
                   [self.peripherale writeValue:_successData forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                   NSLog(@"隨機數(shù)驗證成功");
               }
               
               //隨機數(shù)驗證成功之后
               if ([string3 isEqualToString:@"<01000501 0080>"]) {
                   //發(fā)送第一包數(shù)據(jù)包
                   [self.peripherale writeValue:self.packArray[_sendNumber] forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                   NSLog(@"發(fā)送的包 %@",self.packArray[_sendNumber]);
                   _sendNumber++;
                   [self setValue:[NSString stringWithFormat:@"%d",_sendNumber] forKey:@"sendNumber"];
               }
           }
           
           /*第二種大情況
            1.校驗發(fā)送的包是否收到了
            2.取消升級
            */
           else if ([str isEqualToString:@"<ab100000 00001000>"]) {
               
               NSData * data3 = [_dataArray[arrayCount-1] subdataWithRange:NSMakeRange(0, 5)];
               NSString * string3 = [NSString stringWithFormat:@"%@",data3];
               
               if ([string3 isEqualToString:@"<01000804 00>"] && _sendNumber < self.allSection-1) {
                   //發(fā)送數(shù)據(jù)包
                   [self.peripherale writeValue:self.packArray[_sendNumber] forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                   NSLog(@"發(fā)送的包 %@",self.packArray[_sendNumber]);
                   _sendNumber++;
                   [self setValue:[NSString stringWithFormat:@"%d",_sendNumber] forKey:@"sendNumber"];
               }
               //發(fā)送至最后一包的時候
               else if ([string3 isEqualToString:@"<01000804 00>"] && _sendNumber == self.allSection-1) {
                   
                   [self.peripherale writeValue:self.lastData forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                   NSLog(@"發(fā)送了最后一條指令");
                   //確保進度條顯示到100%
                   _sendNumber++;
                   [self setValue:[NSString stringWithFormat:@"%d",_sendNumber] forKey:@"sendNumber"];
                   //把包數(shù)重新歸零
                   _sendNumber = 0;
                   NSLog(@"%lu %ld",(unsigned long)_dataArray.count,self.allSection);
               }
               
               
           }
           /*第三種大情況
            1.發(fā)送完畢 lastData 之后
            */
           else if ([str isEqualToString:@"<ab100000 00000700>"]) {
               
               NSString * string33 = [NSString stringWithFormat:@"%@",_dataArray[arrayCount-1]];
               
               if ([string33 isEqualToString:@"<01008001 0000>"] && (_dataArray.count-9)/3 == self.allSection)
               {
                   NSLog(@"藍牙數(shù)據(jù)傳輸成功 %@",_dataArray.lastObject);
                   [DFULocalNotification registerLocalNotification:@"藍牙數(shù)據(jù)傳輸完成"];
               }
               else if([string33 isEqualToString:@"<01008001 0000>"] == NO && (_dataArray.count-9)/3 == self.allSection)
               {
                   NSLog(@"藍牙數(shù)據(jù)傳輸錯誤 %@",_dataArray.lastObject);
                   [DFULocalNotification registerLocalNotification:@"藍牙數(shù)據(jù)傳輸錯誤"];
               }
           }
       }
    }
}

重點就是在這個回調(diào)函數(shù)里面,至于其他的文件解讀盛撑,加密碎节,校驗什么的我就不上代碼了,主要還是給大家提供一種思路吧抵卫!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狮荔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子介粘,更是在濱河造成了極大的恐慌殖氏,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姻采,死亡現(xiàn)場離奇詭異雅采,居然都是意外死亡,警方通過查閱死者的電腦和手機慨亲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門婚瓜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人刑棵,你說我怎么就攤上這事巴刻。” “怎么了蛉签?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵胡陪,是天一觀的道長。 經(jīng)常有香客問我碍舍,道長柠座,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任片橡,我火速辦了婚禮妈经,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己吹泡,他們只是感情好录煤,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著荞胡,像睡著了一般妈踊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泪漂,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天廊营,我揣著相機與錄音,去河邊找鬼萝勤。 笑死露筒,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的敌卓。 我是一名探鬼主播慎式,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼趟径!你這毒婦竟也來了瘪吏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蜗巧,失蹤者是張志新(化名)和其女友劉穎掌眠,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幕屹,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡蓝丙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了望拖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渺尘。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖说敏,靈堂內(nèi)的尸體忽然破棺而出鸥跟,到底是詐尸還是另有隱情,我是刑警寧澤像云,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布锌雀,位于F島的核電站蚂夕,受9級特大地震影響迅诬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜婿牍,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一侈贷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦俏蛮、人聲如沸撑蚌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽争涌。三九已至,卻和暖如春辣恋,著一層夾襖步出監(jiān)牢的瞬間亮垫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工伟骨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饮潦,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓携狭,卻偏偏與公主長得像继蜡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逛腿,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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