IOS蓝牙
2.蓝牙外设必须是4.0以上(2.0需要MFI认证),否则无法开发。蓝牙4.0设备因其低功耗也被称为BLE。
3.CoreBluetooth框架的核心其实是两件事。
3.1外围设备
3.2?中心的
4.服务特性:简而言之,外接蓝牙有几个服务service(服务你可以知道蓝牙有什么),每个服务又有几个特性feature(特性你可以知道来说明这个服务的属性)。
5.描述符用于描述特征变量的属性。例如,描述符可以指定可读的描述,或者特征变量的可接受范围,或者特征变量的特定单位。
?3.1为蓝牙管理创建CBCentralManager的实例;
?3.2搜索和扫描外围设备;
?3.3连接外围设备;
?3.4获取外围服务;
?3.5获取服务的特点;
?3.6从外围设备读取数据;
?3.7向外围设备发送(写入)数据。
?4.1初始化
DISPATCH _ QUEUE _ t central QUEUE = DISPATCH _ QUEUE _ create(" central QUEUE ",DISPATCH _ QUEUE _ SERIAL);
ns dictionary * DIC = @ { cbcentralmanageroptionrestore identifier key:restore identifier };
self . central manager =[[cbcentral manager alloc]initWithDelegate:self queue:central queue options:DIC];
cbcentralmanagementstoreidentifierkey对应于一个唯一的标识字符串,在终止蓝牙进程并恢复连接时使用该字符串。
4.2扫描
/*
?*扫描设备
?*/
-(void)scanForDevices:(NSError * *)错误
{
if(CBCentralManagerStatePoweredOn = = self . centralmanager . state){
//检索连接的服务设备。
ns array * retrieved peripherals =[self。centralManagerretrieveConnectedPeripheralsWithServices:@[self。service uuid]];
for(CB peripheral * peripheral in retrieved peripherals){
//NSLog(@ "检索到的外设:%@ ",外设);
【自我。delegate client:self did discover device:peripheral . identifier];
}
//开始扫描
如果(自我。advertisementUUID) {
【自我。central manager scanForPeripheralsWithServices:@[self。advertisementUUID ]选项:@ { CBCentralManagerScanOptionAllowDuplicatesKey:@ YES }];
}否则{
【自我。centralManager scanForPeripheralsWithServices:nil options:@ { CBCentralManagerScanOptionAllowDuplicatesKey:@ YES }];
//[self . central manager scanForPeripheralsWithServices:nil options:nil];
}
}否则{
如果(错误!= NULL ) {
* error =[NSErrorerrorWithDomain:HCErrorDomaincode:(srvclienterror unknown+self . central manager . state)userInfo:nil];
NSLog(@ "[NSError error with domain:HC error domain code:(srvclienterror unknown+self . central manager . state)userInfo:nil];");
}
}
}
4.3外围设备的发现
-(void)central manager:(cbcentral manager *)central discover peripheral:(CBPeripheral *)peripheral advertisement data:(ns dictionary *)advertisement data RSSI:(ns number *)RSSI {
ns string * peripheral name = peripheral . name;
if(peripheral name = = nil | | peripheral name . length = = 0){
返回;
}
if([peripheralNameisEqualToString:SRV _ CLIENT _ DEV _ NAME]| |[peripheralNameisEqualToString:SRV _ CLIENT _ DFU _ NAME]){
}
}
4.4连接外围设备
//蓝牙连接成功回拨
-(void)central manager:(cbcentral manager *)centraldconnectperipheral:(CBPeripheral *)peripheral {
【自我。central manager stopScan];
peripheral.delegate=自我;
自我。command no = 0;
NSLog(@"[D] CentralManager发现服务。");
NSLog(@“% @”),self。周边);
self .peripheral.delegate = self
【自我。外设发现服务:@[ self。service uuid]];
NSLog(@“% @”),self。service uuid);
//定期获取RSSI
如果(自我。needReadRSSI) {
[self readperipheral RSSI];
如果(!自我。rssiTimer) {
自我。rssiTimer =[ns timer scheduledTimerWithTimeInterval:5.0
?目标:自我
选择器:@selector (readPeripheralRSSI)
用户信息:无
重复:是];
}
}
}
#pragma?马克?连接外围设备-失败
-?(void)central manager:(cbcentral manager?*)中央?didFailToConnectPeripheral:(CB peripheral?*)外设?错误:(n错误?*)错误{
NSLog(@“% @”,?错误);
}
#pragma?马克?取消与外围设备的连接回拨。
-?(void)central manager:(cbcentral manager?*)中央?didisconnectperipheral:(CB peripheral?*)外设?错误:(n错误?*)错误{
NSLog(@“% @”,?周边);
}
4.5?从外围设备获取服务
//发现服务的回调
-(void)peripheral:(CB peripheral *)peripheral ddiscoverservices:(NSError *)错误
{
NSLog(@“% @-didDiscoverServices”,外设);
如果(错误){
NSLog(@ "[E]peripheral didiscoverservices错误:%@ ",error . localized description);
[自我取消连接];
返回;
}
for(CB service * peripheral . services中的服务){
NSLog(@"[D]发现特征。For service = %@ ",service);
[peripheral discover characters:nil for service:service];
}
}
//找到功能的回调
-(void)peripheral:(CB peripheral *)peripheral diddiscovercharactersforservice:(CB service *)服务错误:(NSError *)错误
{
如果(错误){
NSLog(@ "[E]peripheral didiscovercharactersforservice错误:%@ ",error . localized description);
[自我取消连接];
返回;
}
NSLog(@ "[D]peripheral discover characters = % @ ",service.characteristics
//订阅功能
for(CB character istic * service . character istics中的特性){
if(特性.属性& amp(cbcharacterypropertyinotify | cbcharacterypropertypindicate)){
如果(!character ization . is notifying){
如果(【自我。ignoreCharacteristicUUIDscontainsObject:特征。UUID]) {
继续;
}
NSLog(@"[D]启用通知值。For特性= %@ ",特性);
//d订阅功能在数据经常更改时使用setNotifyValue,在数据不经常更改时使用readValueForCharacteristic。
[peripheralsetNotifyValue:YES for characteristic:character istic];
}
}
}
}
//订阅后回调
-(void)peripheral:(CB peripheral *)peripheral diupdatenotificationstateforcharacteristic:(CB character istic *)特征错误:(NSError *)错误
{
如果(错误){
NSLog(@ "[E]peripheral diupdatenotificationstateforcharacterical error:% @ ",error . localized description);
[自我取消连接];
返回;
}
if([self isallcharacternotificationenabled]){
NSLog(@“订阅成功”);
//authorizer request授权验证
【自我。delegate clientiddprepareforoperation:self];
}
//[self . delegate clientiddprepareforoperation:self];
}
4.6?从外围设备读取数据
//外设主动发送数据,包括写命令后主动返回的状态读取数据的回调。
-(void)peripheral:(CB peripheral *)peripheral dupdatevalue for character istic:(CB character istic *)character istic error:(NSError *)error
{
如果(错误){
NSLog(@ "[E]peripheral didupdatevalueforcharacterical error:% @ % @ ",error.localizedDescription,characteristic
[自我取消连接];
[自我清理操作意外];
返回;
}
NSLog(@“% @”,外设);
NSLog(@“% @”,特征);
【自我。委托客户:self diddupdatevalueforcharacteristic:character istic。UUID价值:特性.价值];
如果(【特点。UUIDisEqual:自我。ctrl ptuid]){
if(CTRLPTProgressWaitResp = = self。ctrlptProgress) {
?}
}
?}
4.7?向外围设备发送(写入)数据。
-(BOOL)performOperationSegment:(CB character istic *)特征
{
BOOL isLastSegment
uint 8 _ t segment[20];
uint 16 _ tindex = 0;
uint 16 _ tsegLength;
NSIntegerforwardLength = self . forward flow . length;
if ((forwardLength - self。forwardOffset)>(20个索引)){
isLastSegment =否;
segLength = (20-索引);
}否则{
isLastSegment = YES
segLength = (forwardLength - self。forward offset);
}
memcpy(& amp;段[索引],& ampself .forwardFlow.bytes[ self。forwardOffset],segLength
自我。forward offset+= seg length;
index+= seg length;
ns data * writeData =[ns datadatawithbytes:segment length:index];
NSLog(@"[D] Write value = %@。For characteristic = %@ ",writeData,character istic);
【自我。peripheral write value:writeData for characteristic:character istic type:cbcharacteristwritewithresponse];//对于控件蓝牙来说,数据写入要求很快,writewithspoce的写入时间是writewithspoce的2.3倍,所以尽量重写为writewithspoce,提高写入速度。
return isLastSegment
?}
//是否写成功回调?
-(void)peripheral:(CB peripheral *)peripheral diwritevalueforcharacter istic:(CB character istic *)character istic error:(NSError *)error
{
如果(错误){
NSLog(@ "[E]peripheral diwritevalueforcharacterical error:% @ ",error);
[自我取消连接];
[自我清理操作意外];
返回;
}
NSLog(@“写入成功-%@”,特征);
如果(【特点。UUIDisEqual:自我。ctrl ptuid]){
if(CTRLPTProgressWritting = = self。ctrlptProgress) {
if([self performOperationSegment:character istic]){
自我。ctrlptProgress = CTRLPTProgressWaitResp;
self . backward flow . length = 0;
自我。backwardOffset = 0;
}
}
}
}
4.8如何解析蓝牙数据
//判断是否是第一个包,如果是,取出包长。
if (0== self。backwardOffset & amp& amp长度& gt=2) {
uint 16 _ tcommandLength;
【特性数据getbytes:& amp;commandLengthlength:sizeof(command length)];
offset+= sizeof(command length);
自我。backwardLength = commandLength
【自我。backwardfloappenddata:[characterizedatasubdatawithrange:NSMakeRange(offset,length-offset)]];
}否则{
【自我。backwardfloappenddata:character istic data];
}