蓝牙为CC2541 ios升级蓝牙固件;
1.头文件
#import <CoreBluetooth/CoreBluetooth.h>
升级要用到的ID
#define BT_OAD_SERVICE @"F000FFC0-0451-4000-B000-000000000000"
#define BT_OAD_IMAGE_NOTIFY @"F000FFC1-0451-4000-B000-000000000000"
#define BT_OAD_IMAGE_BLOCK_REQUEST @"F000FFC2-0451-4000-B000-000000000000"
2.获取蓝牙列表,选择需要升级的蓝牙
3.获取所有的特征值,找到我们需要的通道,设置通道的模式为监测通道变化
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
传过去所需的参数
[controller setCharacteristic_oad_1:connectDic[BT_OAD_IMAGE_NOTIFY]];通道1
[controller setCharacteristic_oad_2:connectDic[BT_OAD_IMAGE_BLOCK_REQUEST]]通道2
[controller setDetailItem:self.detailItem];//蓝牙CBPeripheral
4.指定蓝牙的代理和代理方法
self.detailItem.delegate = self;
//[characteristic.value bytes]- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
5.选择要升级的文件(这里是本地)
NSString *filePathA = [[NSBundle mainBundle] pathForResource:@"ImageA" ofType:@"bin"];
NSString *filePathB = [[NSBundle mainBundle] pathForResource:@"ImageB" ofType:@"bin"];
oad_A_Data = [NSData dataWithContentsOfFile:filePathA];
oad_B_Data = [NSData dataWithContentsOfFile:filePathB];
if (row == 1) {
oadData = oad_A_Data;
[self sendBlueToothUP];
}else if (row == 2) {
oadData = oad_B_Data;
[self sendBlueToothUP];
}
6.开始进行蓝牙升级:
(1)发送一个字节数据来获取蓝牙设备的当前设备信息
- (void)sendBlueToothUP{
if (!self.characteristic_oad_1||!self.characteristic_oad_2) {
[[AlertShowView sharedInstance] showMessage:@"通道错误"];return;}
Byte byte[] = {};
NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
[self.detailItem writeValue:data forCharacteristic:self.characteristic_oad_1 type:CBCharacteristicWriteWithResponse];
}
(2)在代理处接收返回数据
- (void)readValueWithCharacteristics:(CBCharacteristic *)characteristic andPer:(CBPeripheral *)peripheral{
NSLog(@"\\nreadValue-%@",characteristic.value);
if ([characteristic.UUID.UUIDString isEqualToString:BT_OAD_IMAGE_NOTIFY]) {
if (characteristic.value) {
[self compareVerWithCharacteristics:characteristic];}
}}
(3)处理接收的数据,如果版本不相同,就把本地文件的固件信息通过通道1发送过去;
固件信息包含的信息有:固件版本、固件长度、固件类型
- (void)compareVerWithCharacteristics:(CBCharacteristic *)characteristic{
Byte *Cvalue = (Byte *)[characteristic.value bytes];
Byte *Dvalue = (Byte *)[oadData bytes];
if ((Cvalue[0] & 0x01) != ( Dvalue[4] & 0x01)) {//对比版本信息
NSLog(@"可以升级");
x = 0;
Byte byte[] = {Dvalue[4],Dvalue[5],Dvalue[6],Dvalue[7],Dvalue[8],Dvalue[9],Dvalue[10],Dvalue[11]};//本地数据的固件信息
NSData *sendData = [NSData dataWithBytes:byte length:sizeof(byte)];
NSLog(@"%@",sendData);
[self.detailItem writeValue:sendData forCharacteristic:self.characteristic_oad_1 type:CBCharacteristicWriteWithResponse];
}else{
[[AlertShowView sharedInstance] showInView:self.view andMessage:@"版本相同"];
}}
(4)在代理处接收返回数据(如果成功会通过通道2返回数据)
- (void)readValueWithCharacteristics:(CBCharacteristic *)characteristic andPer:(CBPeripheral *)peripheral{
NSLog(@"\\nreadValue-%@",characteristic.value);
if ([characteristic.UUID.UUIDString isEqualToString:BT_OAD_IMAGE_NOTIFY]) {
if (characteristic.value) {
[self compareVerWithCharacteristics:characteristic];}
}else if ([characteristic.UUID.UUIDString isEqualToString:BT_OAD_IMAGE_BLOCK_REQUEST]){
if (characteristic.value) {
[self.detailItem setNotifyValue:NO forCharacteristic:characteristic];//第二中方法才需要
[self startSendData];//第二种方法
//[self sendDataWithCharacteristics:characteristic];//第一种方法
}}}
(5)处理数据,开始发送本地文件;收到的数据是需要发送数据的序号(0000-FFFF,高位在后;0000,0100,0200...FF00,0001,0101...)
此时有两种方法:
第一种是每次都通过接收到的序号来发送数据,就不需要改变蓝牙的发送和接收模式;
第二种是直接按照一定的间隔去发送数据;只要和硬件规定好时间就可以基本保证成功;
由于第一种方法的速度很慢,所以我选择的第二种方式;
(6)设置定时器,间隔时间20ms;由于是直接发送不需要返回所以选择CBCharacteristicWriteWithoutResponse的方式;
- (void)startSendData{
if (!sendTime) {
x = 0;
sendTime = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(sendData:) userInfo:nil repeats:YES];
}}
- (void)sendData:(NSTimer *)t{
Byte *Dvalue = (Byte *)[oadData bytes];
Byte byte[18];
for (int i = 0; i < 18; i++) {
if (i <= 1 ) {
byte[0] = x%256;
byte[1] = x/256;
}else{
if (i - 2 + x*16 < oadData.length) {
byte[i] = Dvalue[i - 2 + x*16];
}else{
byte[i] = 0xFF;
}}}
NSData *sendData = [NSData dataWithBytes:byte length:sizeof(byte)];
NSLog(@"\\n%ld - \\n%@",x,sendData);
[self.detailItem writeValue:sendData forCharacteristic:self.characteristic_oad_2 type:CBCharacteristicWriteWithoutResponse];
x++;
float sendValue = (float)x*16/(float)oadData.length;//进度条
self.textView.titleL.text = [NSString stringWithFormat:@"%.2f%%",sendValue*100];
[self.textView setCCCount:sendValue];
if (x*16 >= oadData.length) {//传输结束
[sendTime invalidate];
[self.textView setCCCount:1.0];
NSString *timeStr = [NSString stringWithFormat:@"升级完毕 时间%f",[[NSDate date] timeIntervalSinceDate:countTime]];
}}
(7)传输结束后,硬件设备会自启,蓝牙会断开;
demo没整理 见谅
https://github.com/huasali/blueToothDemo