IOS Ble蓝牙开发实现方法
程序员文章站
2023-11-22 12:52:16
本篇博文阐述如何开发ble蓝牙。在蓝牙中的一些常见服务,扫描,以及链接;
主蓝牙类文件.h
主蓝牙类文件.m
uuid文件
蓝牙列表展示的文件...
本篇博文阐述如何开发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蓝牙开发实现都详细的描述了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。