藍牙為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.獲取所有的特征值,找到我們需要的通道,設(shè)置通道的模式為監(jiān)測通道變化
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
傳過去所需的參數(shù)
[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)發(fā)送一個字節(jié)數(shù)據(jù)來獲取藍牙設(shè)備的當前設(shè)備信息
- (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)在代理處接收返回數(shù)據(jù)
- (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)處理接收的數(shù)據(jù),如果版本不相同,就把本地文件的固件信息通過通道1發(fā)送過去;
固件信息包含的信息有:固件版本寥枝、固件長度葱弟、固件類型
- (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]};//本地數(shù)據(jù)的固件信息
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)在代理處接收返回數(shù)據(jù)(如果成功會通過通道2返回數(shù)據(jù))
- (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)處理數(shù)據(jù),開始發(fā)送本地文件;收到的數(shù)據(jù)是需要發(fā)送數(shù)據(jù)的序號(0000-FFFF,高位在后;0000,0100,0200...FF00,0001,0101...)
此時有兩種方法:
第一種是每次都通過接收到的序號來發(fā)送數(shù)據(jù),就不需要改變藍牙的發(fā)送和接收模式;
第二種是直接按照一定的間隔去發(fā)送數(shù)據(jù);只要和硬件規(guī)定好時間就可以基本保證成功;
由于第一種方法的速度很慢,所以我選擇的第二種方式;
(6)設(shè)置定時器,間隔時間20ms;由于是直接發(fā)送不需要返回所以選擇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) {//傳輸結(jié)束
[sendTime invalidate];
[self.textView setCCCount:1.0];
NSString *timeStr = [NSString stringWithFormat:@"升級完畢 時間%f",[[NSDate date] timeIntervalSinceDate:countTime]];
}}
(7)傳輸結(jié)束后,硬件設(shè)備會自啟,藍牙會斷開;
demo沒整理 見諒
https://github.com/huasali/blueToothDemo