zoukankan      html  css  js  c++  java
  • iOS蓝牙空中升级(固件升级)

    空中升级又叫固件升级,指你手机从服务器下载下来的包或者数据,通过蓝牙传输给你的外设升级固件。如果你能把蓝牙的基础搞懂,其实也并不是很难,我在这里只不过提供一下思路。

    空中升级略难的地方在于数据处理和交互,尤其要以怎样简单完整的代码来实现数据的读写是重点,这就需要你和硬件工程师的交流和你自己的逻辑思维了。

    在上代码以前,说一下有关蓝牙的传输速度的,因为我开发中碰到较大数据的传输,着实害我费了很多脑筋。
    蓝牙数据传输中有连接延迟。其是为了低功耗考虑,允许从机在跳频过程中不理会主机的跳频指令,继续睡眠一段时间。而主机不能因为从机睡眠而认为其断开连接了。其是1.25毫秒一个单位。明显,这个数值越小,传输速度也高。
    蓝牙BLE协议规定连接参数最小是5,即7.25毫秒;而Android手机规定连接参数最小是8,即10毫秒。iOS规定是16,即20毫秒。
    连接参数完全由主机决定,但从机可以发出更新参数申请,主机可以接受也可以拒绝。Android手机一部接受,而ios比较严格,拒绝的概率比较高。
    一般场景,连接参数设置16,即20毫秒,一般的传输速率是50* 20 = 1000字节/每秒。如果每个连接事件传输更多的包,可以获得更高的传输速率。
    但是以上这种方法并不能真正解决传输的速度快慢,顶多也就相差2倍或者3倍。最好的方法就是在与app每次给蓝牙发送的包数,通畅可能考虑到数据不丢失,都是一包一包的发送,但是在空中升级这里不得已包数必须要多一点,比如一次发送十包,具体还是看你们硬件那边怎么写蓝牙协议了。

    我下面的demo是这样的一个过程:
    1.发送给外设指令,我要空中升级
    ->2.外设给我回OK之后我发送一个随机数(自定义了一种随机算法),验证开始固件升级
    ->3.判断随机数无误,准备发送打包好的数据
    ->4.真正发送打包好的数据(每次发送10包,一包20个字节),这里会重复N多次,看你的原数据包有多大;每次接到我发的包后,外设都会给我会OK否,我收到OK后才会发一下个数据包
    ->5.告诉外设我数据发送完毕,并发送一段指令(包括本次空中升级数据包的大小,还有加密参数什么的)
    ->6.外设给我回OK无误后,才算真正升级完成

    //更新特征的value时调用
    -(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
        if (error) {
            return;
        }
        //找到已经订阅的串口,输出看结果
       if ([[characteristic.UUID UUIDString] isEqualToString:@"6E400003-B5A3-F393-E0A9-E50E24DCCA9E"]) {
           NSLog(@"返回的结果是 = %@",characteristic.value);
           
           [_dataArray addObject:characteristic.value];
           
           NSInteger arrayCount = _dataArray.count;
           //蓝牙每次都会回三条数据
           if (arrayCount%3 == 0) {
               //返回的头
               NSString *str=[[NSString alloc]initWithFormat:@"%@",_dataArray[arrayCount-3]];
    
               /*第一种大情况
                1.发送固件升级指令
                2.发送随机数
                3.验证随机数是否正确
                */
               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;
                   //随机数
                   if (data2.length == 7 ) {
                       randomData1 = [_dataArray[arrayCount-1] subdataWithRange:NSMakeRange(5, 1)];
                       randomData2 = [_dataArray[arrayCount-1] subdataWithRange:NSMakeRange(6, 1)];
                   }
                   
                   //发起固件升级之后回的
                   if ([string3 isEqualToString:@"<01008204 00010000 00>"]) {
                       //写入随机数
                       [self.peripherale writeValue:self.randomData forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                       NSLog(@"写入的随机数 %@",self.randomData);
                   }
                   
                   //写入随机数之后回的
                   if ([randomData1 isEqualToData:[_calculateRandom subdataWithRange:NSMakeRange(13, 1)]] && [randomData2 isEqualToData:[_calculateRandom subdataWithRange:NSMakeRange(14, 1)]] && [keyHeadStr isEqualToString:@"<06>"]){
                       
                       //随机数验证成功
                       [self.peripherale writeValue:_successData forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                       NSLog(@"随机数验证成功");
                   }
                   
                   //随机数验证成功之后
                   if ([string3 isEqualToString:@"<01000501 0080>"]) {
                       //发送第一包数据包
                       [self.peripherale writeValue:self.packArray[_sendNumber] forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                       NSLog(@"发送的包 %@",self.packArray[_sendNumber]);
                       _sendNumber++;
                       [self setValue:[NSString stringWithFormat:@"%d",_sendNumber] forKey:@"sendNumber"];
                   }
               }
               
               /*第二种大情况
                1.校验发送的包是否收到了
                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) {
                       //发送数据包
                       [self.peripherale writeValue:self.packArray[_sendNumber] forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                       NSLog(@"发送的包 %@",self.packArray[_sendNumber]);
                       _sendNumber++;
                       [self setValue:[NSString stringWithFormat:@"%d",_sendNumber] forKey:@"sendNumber"];
                   }
                   //发送至最后一包的时候
                   else if ([string3 isEqualToString:@"<01000804 00>"] && _sendNumber == self.allSection-1) {
                       
                       [self.peripherale writeValue:self.lastData forCharacteristic:self.TX_Characteristic type:CBCharacteristicWriteWithResponse];
                       NSLog(@"发送了最后一条指令");
                       //确保进度条显示到100%
                       _sendNumber++;
                       [self setValue:[NSString stringWithFormat:@"%d",_sendNumber] forKey:@"sendNumber"];
                       //把包数重新归零
                       _sendNumber = 0;
                       NSLog(@"%lu %ld",(unsigned long)_dataArray.count,self.allSection);
                   }
                   
                   
               }
               /*第三种大情况
                1.发送完毕 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(@"蓝牙数据传输成功 %@",_dataArray.lastObject);
                       [DFULocalNotification registerLocalNotification:@"蓝牙数据传输完成"];
                   }
                   else if([string33 isEqualToString:@"<01008001 0000>"] == NO && (_dataArray.count-9)/3 == self.allSection)
                   {
                       NSLog(@"蓝牙数据传输错误 %@",_dataArray.lastObject);
                       [DFULocalNotification registerLocalNotification:@"蓝牙数据传输错误"];
                   }
               }
           }
        }
    }
    

    重点就是在这个回调函数里面,至于其他的文件解读,加密,校验什么的我就不上代码了,主要还是给大家提供一种思路吧!

  • 相关阅读:
    自定义组件要加@click方法
    绑定样式
    647. Palindromic Substrings
    215. Kth Largest Element in an Array
    448. Find All Numbers Disappeared in an Array
    287. Find the Duplicate Number
    283. Move Zeroes
    234. Palindrome Linked List
    202. Happy Number
    217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/9231218.html
Copyright © 2011-2022 走看看