IOS之BLE蓝牙读取数据与写入数据

【IOS之BLE蓝牙读取数据与写入数据】1.本篇文章归纳了详细的蓝牙读取,与蓝牙写入的通信。
2.借助公司最近一直研发蓝牙设备项目,博主一路走过来,也遇到不少的坑,希望在此能够给予更多看官的帮助。

  • 蓝牙的读取
  • UUID的主要类文件,归纳放置在一个文件:Constants.h
#define APP_NAME@"DishTemp"//温度值功能: 发送实时温度数据, 572.0ㄈ(共7个字节),字符串形式.1 #define BOOT_TEMPVALUE_UUID [CBUUID UUIDWithString:@"此处为你们硬件工程师提供的UUID"]/* OTA Upgrade */ #pragma mark - OTA Upgrade#define FLASH_ARRAY_ID@"flashArrayID" #define FLASH_ROW_NUMBER@"flashRowNumber"#define COMMAND_START_BYTE0x01 #define COMMAND_END_BYTE0x17 //Bootloader command codes#define VERIFY_CHECKSUM0x31 #define GET_FLASH_SIZE0x32 #define SEND_DATA0x37 #define ENTER_BOOTLOADER0x38 #define PROGRAM_ROW0x39 #define VERIFY_ROW0x3A #define EXIT_BOOTLOADER0x3B// Bootloader status/Error codes#define SUCCESS@"0x00" #define ERROR_FILE@"0x01" #define ERROR_EOF@"0x02" #define ERROR_LENGTH@"0x03" #define ERROR_DATA@"0x04" #define ERROR_COMMAND@"0x05" #define ERROR_DEVICE@"0x06" #define ERROR_VERSION@"0x07" #define ERROR_CHECKSUM@"0x08" #define ERROR_ARRAY@"0x09" #define ERROR_ROW@"0x0A" #define ERROR_BOOTLOADER@"0x0B" #define ERROR_APPLICATION@"0x0C" #define ERROR_ACTIVE@"0x0D" #define ERROR_UNKNOWN@"0x0F" #define ERROR_ABORT@"0xFF"#define UPGRADE_BTN_TITLE_FOR_SEPERATE_SELECTION@"NEXT" #define UPGRADE_BTN_TITLE_DEFAULT@"UPGRADE"#define COMMAND_START_BYTE0x01 #define COMMAND_END_BYTE0x17#define CHECK_SUM@"checkSum" #define CRC_16@"crc_16" #define ROW_DATA@"rowData"/* File parsing alerts */ #define FILE_FORMAT_ERROR@"FileFormatError" #define PARSING_ERROR@"ParsingError" #define FILE_EMPTY_ERROR@"FileEmpty"#define LOCALIZEDSTRING(string) NSLocalizedString(string, nil)

蓝牙链接上之后,读取到服务:BlueHelp.m
//只要扫描到特征就会调用,其中的外设和服务就是特征所在的外设和服务 - (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]; }//Tempunit else if([characteristic.UUID isEqual:BOOT_TEMPUNIT_UUID]){ _sendtempunitcharateristic = characteristic; [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } else{ .......... } } } }

得到蓝牙温度,现在就需要解析温度数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { BOOL ota = [_userDefaults getOta]; NSLog(@"ISOTA is %d",ota); //不是OTA的情况 也不是发送数据的情况 //顺序依次为 温度是否正常->温度值->温度符号->温度地址->温度报警值->温度报警静音->温度报警开关->电压提示 if(!ota&&!_isSendData){ NSString *temp=[self getTempTMWData:characteristic]; NSArray *tmp = [temp componentsSeparatedByString:@","]; NSString *nomal = tmp[0]; NSString *temptemp = tmp[1]; NSString *tempunit = tmp[2]; int tempaddre = [tmp[3] intValue]; // NSLog(@"DSADASFDSGFG%@sss%@www%@",nomal,temptemp,tempunit); self.currentDate = [NSDate date]; NSString *dateString = [_dateformatter stringFromDate:self.currentDate]; NSDate *logDate = [_dateformatter dateFromString:dateString]; long logTime= (long)[logDate timeIntervalSince1970]; //如果要等于F的时候 if(_currentTime!=logTime){ if([tempunit isEqualToString:@"F"]){ //float floatString = [temptemp floatValue]; //float aa = [_commonUtil convertFahrenheitToCelcius:floatString]; //正常的时候 if(tempaddre==0){ //NSString *ftempWendu =[NSString stringWithFormat:@"%f",aa]; //NSString *ftempSymbol = @"C"; //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:ftempWendu saveTempSymbol:ftempSymbol saveTemptime:logTime]; }else if(tempaddre==1){ //NSString *ftempSymbol = @"C"; //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:@"999" saveTempSymbol:ftempSymbol saveTemptime:logTime]; } }else{ if(tempaddre==0){ //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:temptemp saveTempSymbol:tempunit saveTemptime:logTime]; }else if(tempaddre==1){ //[_tempDB saveTempname:_deviceName saveTempaddre:tempaddre saveTempTemp:@"999" saveTempSymbol:tempunit saveTemptime:logTime]; } } _currentTime = logTime; }//发送所有数据 NSDictionary *tempDict = [NSDictionary dictionaryWithObject:temp forKey:@"tempData"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"tempNofiction" object:nil userInfo:tempDict]; }

引入BlueHelp.h文件
#import //导入蓝牙框架 #import #import "DeviceModel.h" #import "Constants.h" #import "CommonUserDefaults.h" #import "CommonUtil.h" #import "TempDB.h"#define COMMAND_PACKET_MIN_SIZE7@interface BlueHelp : NSObject//蓝牙的设备搜索显示在列表中 @property (nonatomic, strong) NSMutableArray *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) 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; @end

此时就是显示的界面,接收蓝牙的广播
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tempCompletion:) name:@"tempNofiction" object:nil];

接收到广播,把信息展示出来
-(void)tempCompletion:(NSNotification*)notification{ //第一次加载的时候需要这么执行 if(_onceLoad){ [_progress closeLoadingView]; _tempView.leftView.hidden = FALSE; _tempView.rightView.hidden = FALSE; _onceLoad = FALSE; }//顺序依次为 温度是否正常->温度值->温度符号->温度地址->温度报警值->温度报警静音->温度报警开关->电压提示-静音报警开关 // 0-1-2-3-4-5-6-7-8 NSDictionary *temp = [notification userInfo]; NSString *tempData = https://www.it610.com/article/[temp objectForKey:@"tempData"]; //测试打印 //NSLog(@"传过来的温度是:%@",tempData); NSArray *tp = [tempData componentsSeparatedByString:@","]; _temptemp = tp[0]; //时实温度 _TmaxTemp = tp[1]; //最大温度 _tempunit = tp[2]; //温度符号 _mutesound = [tp[3] intValue]; //低电压判断//save temp... unit. //存储地址 [_userDefaults saveMacAddre:self.maclistdata]; [_userDefaults saveTempUnit:_tempunit macAddre:self.maclistdata]; [_userDefaults saveCorF:_tempunit macAddre:self.maclistdata]; //save high alarm.//当为第一次运行的时候 都统一默认为5秒 if(_onceRun&&!_onceRunApp){_tempView.txtaddre.text = self.maclistdata; //存入蓝牙地址 if(self.maclistdata!=nil){ [_userDefaults saveMacAddre:self.maclistdata]; } //存入温度符号 if(_tempunit!=nil){ [_userDefaults saveTempUnit:_tempunit macAddre:self.maclistdata]; }//获取当前的时间 NSString *time = [_userDefaults getUpdateTime:self.maclistdata]; if(time!=nil){ [_blueHelp writeIntervalTime:time]; }else{ [_blueHelp writeIntervalTime:@"5"]; }//调式程序 //[_blueHelp writeHighAlarm:@"-10"]; //发送cal值 NSString *cal = [_userDefaults getCal:self.maclistdata currentSymbol:_tempunit]; if([cal isEqualToString:@""]||cal==nil){ cal = @"0"; } NSString *calSymbol = [_userDefaults getCalSymbol:self.maclistdata]; if([_tempunit isEqualToString:calSymbol]){ [self sendCalSet:cal]; }else{ if([_tempunit isEqualToString:@"°C"]){ if([calSymbol isEqualToString:@"°F"]){ float a = [cal floatValue]; float b = [_commonUtil convertFahrenheitCalCelcius:a]; NSString *bb = [NSString stringWithFormat:@"%0.1f",b]; [self sendCalSet:bb]; } }else{ if([calSymbol isEqualToString:@"°C"]){ float a = [cal floatValue]; float b = [_commonUtil convertCelciusCalFahren:a]; NSString *bb = [NSString stringWithFormat:@"%0.1f",b]; [self sendCalSet:bb]; } } } _onceRun = FALSE; }/* * 更新于 2017/11/16 14:44 */ //为1的时候显示 低电量 当为低电量的时候所有的事件也要执行 [self displayFont:_voltage]; [self showData]; }

2.写入蓝牙的功能
  1. 首先根据自己的项目需求
  2. 然后跟硬件工程师协商好
  3. 发送的字符规格,节数等等
如下:发送“pd”,给底层,为设备的关机
NSString *otapd = @"PD"; [_blueHelp writeBluePD:otapd]; //调用写入的类,发送pd

//PD设备关机 -(void)writeBluePD:(NSString *)value{ _isSendData = https://www.it610.com/article/TRUE; [self writeClearPD:value forCharacteristic:_senddoutstrateristic]; }

//写入PD的区块 -(void)writeClearPD:(NSString *)value forCharacteristic:(CBCharacteristic *)characteristic { NSData *data = https://www.it610.com/article/[value dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"send data pd and is:%@",data); //is no write bluetooth data if(_senddoutstrateristic.properties & CBCharacteristicPropertyWriteWithoutResponse) { //send phone on bluetooth data [_selectperipheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse]; }else { [_selectperipheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; } //NSLog(@"已经向外设%@的特征值%@写入数据",_peripheral.name,characteristic.description); _isSendData = https://www.it610.com/article/FALSE; }

BlueHelp.h文件
//发送字符串'PD'机子关机(3个字节) @property (nonatomic,strong) CBCharacteristic *senddoutstrateristic; //写入设备的开关按钮 -(void)writeBluePD:(NSString *)value;

BuleHelp.m文件
读取到蓝牙UUID服务的时候,加上这个 //发送字符串'PD'机子关机(3个字节) else if([characteristic.UUID isEqual:BOOT_OUTSTRING_UUID]){ _senddoutstrateristic = characteristic; [peripheral setNotifyValue:YES forCharacteristic:characteristic]; }

最后,经过测试完毕,蓝牙的读取和写入就阐述到此,如有不懂的可以留言。若有帮助,麻烦点个赞,谢谢您的阅读!~

    推荐阅读