本篇博文阐述如何开发Ble蓝牙。在蓝牙中的一些常见服务,扫描,以及链接; 主蓝牙类文件.h 主蓝牙类文件.m UUID文件 蓝牙列表展示的文件 一:引入Ble蓝牙的框架CoreBluetooth/CoreBluetoot
          本篇博文阐述如何开发Ble蓝牙。在蓝牙中的一些常见服务,扫描,以及链接;
- 主蓝牙类文件.h
- 主蓝牙类文件.m
- UUID文件
- 蓝牙列表展示的文件
 
一:引入Ble蓝牙的框架<CoreBluetooth/CoreBluetooth.h>
BuleHelp.h
#import <Foundation/Foundation.h> //导入蓝牙框架 #import <CoreBluetooth/CoreBluetooth.h> #import "DeviceModel.h" #import "Constants.h" #import "CommonUserDefaults.h" #import "CommonUtil.h" #import "TempDB.h" #define COMMAND_PACKET_MIN_SIZE 7 @interface BlueHelp : NSObject //蓝牙的设备搜索显示在列表中 @property (nonatomic, strong) NSMutableArray <CBPeripheral*>*periperals; //连接peripheral @property(nonatomic,strong) CBPeripheral *peripheral; //连接peripheral @property(nonatomic,strong) CBPeripheral *selectperipheral; //中心管理者 @property (nonatomic, strong) CBCentralManager *centerManager; @property (nonatomic,strong) DeviceModel *deviceModel; //设备列表 @property (nonatomic,strong) NSMutableArray *deviceList; @property (nonatomic,strong) NSMutableArray *commandArray; //是否进行ota升级 @property (nonatomic) BOOL isOta; @property (nonatomic) BOOL isWritePacketDataSuccess; @property (strong,nonatomic) NSString * checkSumType; /*! * @property isApplicationValid * * @discussion flag used to check whether the application writing is success * */ @property (nonatomic) BOOL isApplicationValid; /*! * @property checkSum * * @discussion checkSum received from the device for writing a single row * */ @property (assign) uint8_t checkSum; /*! * @property startRowNumber * * @discussion Device flash start row number * */ @property (nonatomic) int startRowNumber; /*! * @property endRowNumber * * @discussion Device flash end row number * */ @property (nonatomic) int endRowNumber; /*! * @property siliconIDString * * @discussion siliconID from the device response * */ @property (strong,nonatomic) NSString *siliconIDString; /*! * @property siliconRevString * * @discussion silicon rev from the device response * */ @property (strong,nonatomic) NSString *siliconRevString; //是否发送数据 @property (nonatomic) BOOL isSendData; @property (strong,nonatomic) CommonUtil *commonUtil; @property (strong,nonatomic) TempDB *tempDB; @property (strong,nonatomic) NSDate *currentDate; //时间格式化 @property(strong,nonatomic) NSDateFormatter *dateformatter; @property(strong,nonatomic) NSString *deviceName; //@property (nonatomic,strong) NSUserDefaults *userDefaults; @property (nonatomic,strong) CommonUserDefaults *userDefaults; //发送温度数据 @property (nonatomic,strong) CBCharacteristic *sendtempcharateristic; //发送OTA数据 @property (nonatomic,strong) CBCharacteristic *sendotacharateristic; //高/低温度数据 //@property (nonatomic,strong) CBCharacteristic *sendhighalarmcharateristic; // //@property (nonatomic,strong) CBCharacteristic *sendlowalarmcharateristic; //ota @property (nonatomic,strong) CBCharacteristic *senddfucharateristic; //发送字符串'CR'清除机子上的最大值(3个字节) @property (nonatomic,strong) CBCharacteristic *senddcrstrateristic; //发送字符串'PD'机子关机(3个字节) @property (nonatomic,strong) CBCharacteristic *senddoutstrateristic; //静音 @property (strong,nonatomic) CBCharacteristic *sendmutealarmcharateristic; //calset @property(strong,nonatomic) CBCharacteristic *sendcalsetcharateristic; //intervaltime @property(strong,nonatomic) CBCharacteristic *sendintervaltimecharateristic; //alarmswitch @property(strong,nonatomic) CBCharacteristic *sendalarmswitchcharateristic; //tempunit @property(strong,nonatomic) CBCharacteristic *sendtempunitcharateristic; @property(strong,nonatomic) CBCharacteristic *sendlowalarmswitchcharateristic; ///<===============方法区块=======================> + (id)sharedManager; -(NSMutableArray *)getDeviceList; -(NSMutableArray *)getPeriperalList; -(void)startScan; //连接蓝牙 -(void)contentBlue:(int) row; //断开蓝牙 -(void)disContentBle; //断开ota的蓝牙连接 -(void)disContentOtaBle; //温度符号 -(void)writeTempUnit:(NSString *)value; //写入报警开关 -(void)writeAlarmSwitch:(NSString *)value; //写入mute alarm -(void)writeMuteAlarm:(NSString *)value; //写入CR CLERVULE -(void)writeClearCR:(NSString *)value; //写入interval time -(void)writeIntervalTime:(NSString *)value; //写入cal set -(void)writeCalSet:(NSString *)value; //写入设备的开关按钮 -(void)writeBluePD:(NSString *)value; //写入低温报警 //-(void)writeLowAlarm:(NSString *)value; // ////写入高温报警 //-(void)writeHighAlarm:(NSString *)value; //OTA固件升级 又称为DFU -(void)writeUpdateOTA:(NSString*)value; -(void)writeBlueOTA:(NSString *)value; -(void)wirteBlueOTAData:(NSData *)value; -(void)writeLowAlarmSwitch:(NSString *)value; -(void) discoverCharacteristicsWithCompletionHandler:(void (^) (BOOL success, NSError *error)) handler; -(void)updateValueForCharacteristicWithCompletionHandler:(void (^) (BOOL success,id command,NSError *error)) handler; -(void) stopUpdate; -(void) setCheckSumType:(NSString *) type; -(NSData *) createCommandPacketWithCommand:(uint8_t)commandCode dataLength:(unsigned short)dataLength data:(NSDictionary *)packetDataDictionary; -(void) writeValueToCharacteristicWithData:(NSData *)data bootLoaderCommandCode:(unsigned short)commandCode; /* * 停止扫描 */ -(void)stopScan; //是否是第一次连接设备 @property(assign,nonatomic) BOOL isconnected; //当前的时间 @property(nonatomic,assign) long currentTime; @property(nonatomic,strong) NSString *macAddre; @property(nonatomic,strong) NSString *macName; -(void)disMainOtaBle; @end
BuleHelp.m
//程序运行后,会自动调用的检查蓝牙的方法 并扫描蓝牙的方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
 if ([central state] == CBCentralManagerStatePoweredOff) {
  NSLog(@"CoreBluetooth BLE hardware is powered off");
 }
 else if ([central state] == CBCentralManagerStatePoweredOn) {
  NSLog(@"CoreBluetooth BLE hardware is powered on and ready");
  [self startScan];
 }
 else if ([central state] == CBCentralManagerStateUnauthorized) {
  NSLog(@"CoreBluetooth BLE state is unauthorized");
 }
 else if ([central state] == CBCentralManagerStateUnknown) {
  NSLog(@"CoreBluetooth BLE state is unknown");
 }
 else if ([central state] == CBCentralManagerStateUnsupported) {
  NSLog(@"CoreBluetooth BLE hardware is unsupported on this platform");
 }
}
/*
 * 程序运行的时候开始扫描
 */
-(void)startScan{
 _periperals = [[NSMutableArray alloc] init];
 _deviceList = [[NSMutableArray alloc] init];
 //2.利用中心设备扫描外部设备
 [_centerManager scanForPeripheralsWithServices:nil options:nil];
}
/*
 * 停止扫描
 */
-(void)stopScan{
 [_centerManager stopScan];
}
/*
 * 设备中可以包含 Device addre地址 放在 key:kCBAdvDataManufacturerData中既可以得到
 * 1.硬件开发工程师 把地址写入到设备的厂家信息中。
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSS{
 //判断如果数组中不包含当前扫描到的外部设备才保存
 if (![_periperals containsObject:peripheral]){
  //包扣3种设备 都需要去搜索
  if([peripheral.name containsString:@"TMW012BT"]||[peripheral.name containsString:@"OTA"]){
   NSLog(@"DATA: %@", advertisementData);
   NSArray *keys = [advertisementData allKeys];
   for (int i = 0; i < [keys count]; ++i) {
    id key = [keys objectAtIndex: i];
    NSString *keyName = (NSString *) key;
    NSData *value = [advertisementData objectForKey: key];
    
    if([keyName isEqualToString:@"kCBAdvDataManufacturerData"]){
     NSLog(@"value is %@",value);
     NSString *result = [self convertDataToHexStr:value];
     NSLog(@"reslut is %@",result);
     if(result!=nil&&result.length>4){
      NSString *d = [result substringFromIndex:4];
      NSLog(@"D IS %@",d);
      // 小写
      //NSString *lower = [test lowercaseString];
      // 大写
      NSString *upper = [d uppercaseString];
      _macAddre = [NSString stringWithFormat:@"S/N:%@",upper];
     }
    }
    
    if([keyName isEqualToString:@"kCBAdvDataLocalName"]){
     NSString *aStr= (NSString*)value;
     NSLog(@"astr is %@",aStr);
     _macName = aStr;
    }
   }
   
   _deviceModel = [DeviceModel new];
   _deviceModel.deviceName = _macName;
   //蓝牙地址
   _deviceModel.deviceAddre = _macAddre;
   
   int rssi = [RSS intValue];
   NSString *range = [NSString stringWithFormat:@"%d",rssi];
   NSString *rs = [NSString stringWithFormat:@"RSSI %@dBm",range];
   //添加到里面
   [self.periperals addObject:peripheral];
   _deviceModel.deviceRssi = rs;
   [_deviceList addObject:_deviceModel];
  }
 }
}
//解析广播里面的数据
-(void)getAdvertisementData:(NSDictionary<NSString *,id> *) advertisementData{
 NSArray *keys = [advertisementData allKeys];
 for (int i = 0; i < [keys count]; ++i) {
  id key = [keys objectAtIndex: i];
  NSString *keyName = (NSString *) key;
  NSObject *value = [advertisementData objectForKey: key];
  
  if([keyName isEqualToString:@"kCBAdvDataManufacturerData"]){
   printf(" key: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding]);
   NSString *values = (NSString *) value;
   NSLog(@"values is %@",values);
  }
 }
}
/*
 * 连接蓝牙设备给外部调用的方法
 * 传入的是相对应的行数
 */
-(void)contentBlue:(int) row{
 [_centerManager connectPeripheral:_periperals[row] options:nil];
}
-(void)disContentBle{
 //关键的断开蓝牙 通知也要停止掉
 if((_peripheral!=nil && _sendtempcharateristic!=nil)){
  [_peripheral setNotifyValue:NO forCharacteristic:_sendtempcharateristic];
  [self disconnectPeripheral:_peripheral];
 }
}
/*
 * 断开ota的 连接
 */
-(void)disContentOtaBle{
 if(_peripheral!=nil && _sendotacharateristic!=nil){
  [_peripheral setNotifyValue:NO forCharacteristic:_sendotacharateristic];
  [self disconnectPeripheral:_peripheral];
 }
}
-(void)disMainOtaBle{
 if(_peripheral!=nil){
  [self disconnectPeripheral:_peripheral];
 }
}
- (void) disconnectPeripheral:(CBPeripheral*)peripheral
{
 [_centerManager cancelPeripheralConnection:peripheral];
}
//连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
 NSLog(@"连接成功");
 if(peripheral!=nil){
  //停止扫描 这个用于自动连接的时候
  [_centerManager stopScan];
  //设备名称
  _deviceName = peripheral.name;
  
  _selectperipheral = peripheral;
  
  peripheral.delegate = self;
  //再去扫描服务
  [peripheral discoverServices:nil];
  
 }
}
//连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
 NSLog(@"连接失败,失败原因:%@",error);
 NSString *disContentBlue = @"discontentblue";
 NSDictionary *blueDiscontent = [NSDictionary dictionaryWithObject:disContentBlue forKey:@"disconnect"];
 //发送广播 连接失败
 [[NSNotificationCenter defaultCenter] postNotificationName:@"disNofiction" object:nil userInfo:blueDiscontent];
}
//断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
 NSLog(@"断开连接");
 NSString *disContentBlue = @"discontentblue";
 //_blueiscon = @"Disconnect";
 NSDictionary *blueDiscontent = [NSDictionary dictionaryWithObject:disContentBlue forKey:@"disconnect"];
 //发送广播 连接失败
 [[NSNotificationCenter defaultCenter] postNotificationName:@"disNofiction" object:nil userInfo:blueDiscontent];
}
//只要扫描到服务就会调用,其中的外设就是服务所在的外设
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
 if (error){
  NSLog(@"扫描服务出现错误,错误原因:%@",error);
 }else{
  //获取外设中所扫描到的服务
  for (CBService *service in peripheral.services){
   //拿到需要扫描的服务,例如FFF0 比如打印温度数据
   //把所有的service打印出来
   //从需要的服务中查找需要的特征
   //从peripheral的services中扫描特征
   [peripheral discoverCharacteristics:nil forService:service];
  }
 }
}
//只要扫描到特征就会调用,其中的外设和服务就是特征所在的外设和服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error{
 if(error){
  NSLog(@"扫描特征出现错误,错误原因:%@",error);
 }else{
  //遍历特征,拿到需要的特征进行处理
  for (CBCharacteristic *characteristic in service.characteristics){
   NSLog(@"characteristic is %@",characteristic.UUID);
   //如果是温度数据处理
   if([characteristic.UUID isEqual:BOOT_TEMPVALUE_UUID]){
    //将全部的特征信息打印出来
    _isconnected = true;
    _peripheral = peripheral;
    _sendtempcharateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   //如果是ota进行ota升级
   else if([characteristic.UUID isEqual:BOOT_OTA_WIRTE_UUID]){
    _peripheral = peripheral;
    _sendotacharateristic = characteristic;
    //设置通知
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    _isOta = TRUE;
    [_userDefaults saveOta:_isOta];
    //[_ setBool:_isOta forKey:@"isOTA"];
    NSString *s = @"OTA";
    NSDictionary *tempOta = [NSDictionary dictionaryWithObject:s forKey:@"ota"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"tempOTA" object:nil userInfo:tempOta];
   }
   //CAL
   else if([characteristic.UUID isEqual:BOOT_CAL_UUID]){
    _sendcalsetcharateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   //interval time
   else if([characteristic.UUID isEqual:BOOT_INTERVALTIME_UUID]){
    _sendintervaltimecharateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   //Tempunit
   else if([characteristic.UUID isEqual:BOOT_TEMPUNIT_UUID]){
    _sendtempunitcharateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   
   //DFU
   else if([characteristic.UUID isEqual:BOOT_DFU_UUID]){
    _senddfucharateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   //发送字符串'CR'清除机子上的最大值(3个字节)
   else if([characteristic.UUID isEqual:BOOT_CRSTRING_UUID]){
    _senddcrstrateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   //发送字符串'PD'机子关机(3个字节)
   else if([characteristic.UUID isEqual:BOOT_OUTSTRING_UUID]){
    _senddoutstrateristic = characteristic;
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
   }
   else{
    
   }
  }
 }
}
/*
 设置通知
 */
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
    characteristic:(CBCharacteristic *)characteristic{
 [peripheral setNotifyValue:YES forCharacteristic:characteristic];
 [_centerManager stopScan];
}
/*
 取消通知
 */
-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral
     characteristic:(CBCharacteristic *)characteristic{
 [peripheral setNotifyValue:NO forCharacteristic:characteristic];
}
/*
 接收数据解析
 */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
 //是否为Ota
 if(!self.isSendOta){
  if(self.readtempcharater == characteristic){
   NSString *tmpData = [self.cmUtil getTempTMWData:characteristic];
   if(tmpData!=nil){
    //开始处理数据
    NSArray *data = [tmpData componentsSeparatedByString:@","];
    TmpModel *tp = [[TmpModel alloc] init];
    tp.tmp = data[0];
    tp.max = data[1];
    tp.unit = data[2];
    //电量
    tp.bat = data[3];
    
    NSDictionary *tempDict = [NSDictionary dictionaryWithObject:tp forKey:@"tempData"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofiction" object:nil userInfo:tempDict];
    if([tp.bat isEqual:@"1"]){
     //低电量广播
     NSDictionary *LowDict = [NSDictionary dictionaryWithObject:tp forKey:@"lowData"];
     [[NSNotificationCenter defaultCenter] postNotificationName:@"lowNofiction" object:nil userInfo:LowDict];
    }
   }
  }
 }
//======================写入数据区块========================//
/*
 写入发送时间
 */
-(void)writeIntervalTime:(NSString *)value periperalData:(CBPeripheral*)periperal{
 if(value!=nil&&periperal!=nil&&self.sendtimecharater!=nil){
  [self writeData:value forCharacteristic:self.sendtimecharater periperalData:periperal];
 }
}
/*
 写入温度单位
 */
-(void)writeTmpUnit:(NSString*)value periperalData:(CBPeripheral*)periperal{
 if(value!=nil&&periperal!=nil&&self.sendunitcharater!=nil){
  [self writeData:value forCharacteristic:self.sendunitcharater periperalData:periperal];
 }
}
/*
 写入Cal值
 */
-(void)writeCalValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
 if(value!=nil&&periperal!=nil&&self.sendcalcharater!=nil){
  [self writeData:value forCharacteristic:self.sendcalcharater periperalData:periperal];
 }
}
/*
 发送Ota使得设备进入Ota
 */
-(void)writeDfuValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
 if(value!=nil&&periperal!=nil&&self.senddfucharater!=nil){
  [self writeData:value forCharacteristic:self.senddfucharater periperalData:periperal];
 }
}
/*
 发送Max Temp实现清零选项
 */
-(void)writeClearValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
 if(value!=nil&&periperal!=nil&&self.sendclearcharater!=nil){
  [self writeData:value forCharacteristic:self.sendclearcharater periperalData:periperal];
 }
}
/*
 发送关机选项实现远程开关机
 */
-(void)writeCloseValue:(NSString *)value periperalData:(CBPeripheral*)periperal{
 if(value!=nil&&periperal!=nil&&self.sendclosecharater!=nil){
  [self writeData:value forCharacteristic:self.sendclosecharater periperalData:periperal];
 }
}
/*
 所有写入的数据处理
 */
-(void)writeData:(NSString *)value forCharacteristic:(CBCharacteristic *)characteristic periperalData:(CBPeripheral*)periperal{
 NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
 if(characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse)
 {
  [periperal writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
 }else
 {
  [periperal writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
 }
}
此篇文章阐述到这,基本BLE蓝牙开发实现都详细的描述了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。
