iOS学习笔记

蓝牙连接以及发送数据

2017-03-29  本文已影响48人  勇不言弃92

1.连接蓝牙的常规代码

1.首先引入库:#import <CoreBluetooth/CoreBluetooth.h>
2.代理:<CBCentralManagerDelegate,CBPeripheralDelegatea>
3.准备设备管理

//创建中心管理者,管理中心设备
self.mgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[self cleanup];
//开始搜索蓝牙设备
[self.mgr scanForPeripheralsWithServices:nil options:nil];

4.代理方法--代码中有注释,特别注意代码中的“kServiceUUID,kCharacteristicUUID,SERVICE_UUID,CHAR_UUID这四个参数”

#pragma mark - 清理蓝牙
//清理缓存
- (void)cleanup
{

if (!self.myPeripheral) {
return;
}

if (self.myPeripheral.state==CBPeripheralStateDisconnected||self.myPeripheral.state == CBPeripheralStateConnecting)
{
self.myPeripheral=nil;
self.characteristic = nil;
return;
}

if (self.service != nil&&self.characteristic!=nil)
{
if (self.characteristic.isNotifying)
{
[self.myPeripheral setNotifyValue:NO forCharacteristic:self.characteristic];
}
}

[self.mgr cancelPeripheralConnection:self.myPeripheral];

[self.mgr stopScan];

self.myPeripheral=nil;
self.service=nil;
self.characteristic=nil;
}

#pragma mark - CBCentralManagerDelegate
//设备蓝牙状态更新
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{

switch (central.state) {
case CBCentralManagerStateUnsupported:
NSLog(@"该设备不支持BLE蓝牙");
break;
case CBCentralManagerStateUnauthorized:
NSLog(@"该设备未授权BLE蓝牙");
break;
case CBCentralManagerStatePoweredOff:
NSLog(@"该设备BLE蓝牙已关闭");
break;
case CBCentralManagerStateUnknown:
NSLog(@"该设备BLE蓝牙发生未知错误");
break;
case CBCentralManagerStateResetting:
NSLog(@"该设备BLE蓝牙重置中");
break;
case CBCentralManagerStatePoweredOn:
[self cleanup];
[self.mgr scanForPeripheralsWithServices:nil options:nil];
break;

default:
NSLog(@"Central Manager did change state");
break;
}
}

//发现外部设备时候调用此方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSString *periName = peripheral.name;

self.myPeripheral = peripheral;
//连接设备,这里是连接了所有设备,应该做的是跟据设备的已知信息去连接设备
[self.mgr connectPeripheral:self.myPeripheral options:nil];
//停止扫描蓝牙
[self.mgr stopScan];
}

//连接蓝牙成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
//发现服务
self.myPeripheral .delegate = self;
[self.myPeripheral  discoverServices:nil];
}

//连接蓝牙失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSString *err = [NSString stringWithFormat:@"连接蓝牙门禁%@失败,原因:%@",peripheral.name,[error localizedDescription]];
NSLog(@"%@",err);
}

//断开蓝牙连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
}


#pragma mark - CBPeripheralDelegate
//外设已经查找到服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if (error) return; //发现服务失败

//遍历所有服务
for (CBService *service in self.myPeripheral.services) {
NSLog(@"%@",service.UUID);
if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]){
self.service = service;
break;
}
}

if (self.service) {

[self.myPeripheral discoverCharacteristics:nil forService:self.service];
}

}

#pragma mark 找到特征时调用

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if (error) return; //发现特征失败

for (CBCharacteristic *characteristic in self.service.characteristics)
{
NSLog(@"%@",characteristic.UUID);
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristicUUID]])
{
self.characteristic = characteristic;
//对此特征设置通知和读取返回数据
[self.myPeripheral setNotifyValue:YES forCharacteristic:self.characteristic];
[self.myPeripheral readValueForCharacteristic:self.characteristic];
[self sendMessageToBle];
break;
}

}
}


- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
NSLog(@"%@",error);
return;
} //发送数据失败

}


- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) return; //接收特征数据失败
NSString *value = [[NSString alloc] initWithData:characteristic.value encoding:NSASCIIStringEncoding];
NSLog(@"value==============%@",value);//蓝牙返回的信息,需要对蓝牙设备做特殊处理才能按照一定的格式返回数据
if ([[value lowercaseString] isEqualToString:@"success"]){

}else if ([[value lowercaseString] isEqualToString:@"fail"]){

}
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) return; //开启特征数据返回通知失败

}

2.iOS开发过程中没有直接获取蓝牙Mac地址的方法,需要从读取的数据中提出

参考MacPu的博客-iOS如果获取蓝牙Mac地址 谢谢!
将“kServiceUUID,kCharacteristicUUID“分别设置为“180A,2A23”,

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) return; //接收特征数据失败
NSString *value = [NSString stringWithFormat:@"%@",characteristic.value];
NSMutableString *macString = [[NSMutableString alloc] init];
[macString appendString:[[value substringWithRange:NSMakeRange(16, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(14, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(12, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(5, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(3, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(1, 2)] uppercaseString]];
NSLog(@"macString:%@",macString);
}

3.向蓝牙设备发送数据,并且接收返回数据

在我的实际操作中,发现每次向蓝牙发送数据的时候总是失败,需要借助下面的代码才能发送成功

#pragma mark - 向蓝牙发送数据
- (void)sendMessageToBle{
//加密数据
int index =  arc4random() % 20;
NSString *doorcode = self.doorArray[index];

NSString *dateStr1 = [NSDate stringFromDate:[NSDate date] withFormat:@"yyyyMMdd"];
NSString *dateStr2 = [NSDate stringFromDate:[NSDate date] withFormat:@"MMddyyyy"];
NSString *dateStr = [NSString stringWithFormat:@"%@%@",dateStr1,dateStr2];

NSString *strA1 = @"OW15LjrCaY2bfcMl";
NSString *strB1 = @"aWuK48JRDPePsYXE";

Byte *A = [self strToByte:dateStr];
Byte *A1 = [self strToByte:strA1];
Byte *B = [self strToByte:doorcode];
Byte *B1 = [self strToByte:strB1];

Byte bleData[16] = {0};
for (int i = 0; i < strA1.length; i ++) {
Byte left = (Byte)(A[i] & A1[i]);
Byte right = (Byte)(B[i] | B1[i]);
bleData[i] = (Byte)(left ^ right);
}
Byte bleMD5[16] ={0};
CC_MD5(bleData, 16, bleMD5);
Byte final[15] = {0};
final[0] = 15;
for (int i = 0; i < 12; i ++) {
final[i + 1] = bleMD5[i];
}
final[13] = 13;
final[14] = 10;

NSData *finalData = [NSData dataWithBytes:final length:15];

[self writeValue:SERVICE_UUID characteristicUUID:CHAR_UUID p:self.myPeripheral data:finalData];
}

-(void) writeValue:(int)serviceUUID characteristicUUID:(int)characteristicUUID p:(CBPeripheral *)p data:(NSData *)data {
//这里对服务值以及特征值做了一下处理,按照硬件的识别方式转换一下
UInt16 s = [self swap:serviceUUID];
UInt16 c = [self swap:characteristicUUID];
NSData *sd = [[NSData alloc] initWithBytes:(char *)&s length:2];
NSData *cd = [[NSData alloc] initWithBytes:(char *)&c length:2];
CBUUID *su = [CBUUID UUIDWithData:sd];
CBUUID *cu = [CBUUID UUIDWithData:cd];
CBService *service = [self findServiceFromUUIDEx:su p:p];
if (!service) {
printf("Could not find service with UUID %s on peripheral with UUID %s\r\n",[self CBUUIDToString:su],[self UUIDToString:(__bridge CFUUIDRef )p.identifier]);
return;
}
CBCharacteristic *characteristic = [self findCharacteristicFromUUIDEx:cu service:service];
if (!characteristic) {
printf("Could not find characteristic with UUID %s on service with UUID %s on peripheral with UUID %s\r\n",[self CBUUIDToString:cu],[self CBUUIDToString:su],[self UUIDToString:(__bridge CFUUIDRef )p.identifier]);
return;
}
[p setNotifyValue:YES forCharacteristic:characteristic];
//写入数据时选择有返回数据/无返回数据
if(characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse)
{
[p writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}else
{
[p writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
}

-(UInt16) swap:(UInt16)s {
UInt16 temp = s << 8;
temp |= (s >> 8);
return temp;
}
-(CBService *) findServiceFromUUIDEx:(CBUUID *)UUID p:(CBPeripheral *)p {
for(int i = 0; i < p.services.count; i++) {
CBService *s = [p.services objectAtIndex:i];
if ([self compareCBUUID:s.UUID UUID2:UUID]) return s;
}
return nil; //Service not found on this peripheral
}
-(int) compareCBUUID:(CBUUID *) UUID1 UUID2:(CBUUID *)UUID2 {
char b1[16];
char b2[16];
[UUID1.data getBytes:b1];
[UUID2.data getBytes:b2];
if (memcmp(b1, b2, UUID1.data.length) == 0)return 1;
else return 0;
}
-(const char *) CBUUIDToString:(CBUUID *) UUID {
return [[UUID.data description] cStringUsingEncoding:NSStringEncodingConversionAllowLossy];
}
-(const char *) UUIDToString:(CFUUIDRef)UUID {
if (!UUID) return "NULL";
CFStringRef s = CFUUIDCreateString(NULL, UUID);
return CFStringGetCStringPtr(s, 0);
}

-(CBCharacteristic *) findCharacteristicFromUUIDEx:(CBUUID *)UUID service:(CBService*)service {
for(int i=0; i < service.characteristics.count; i++) {
CBCharacteristic *c = [service.characteristics objectAtIndex:i];
if ([self compareCBUUID:c.UUID UUID2:UUID]) return c;
}
return nil; //Characteristic not found on this service
}

//字符串转byte
- (Byte *)strToByte:(NSString *)strBefor{
Byte *bt = (Byte *)malloc(16);
for (int i =0; i < strBefor.length; i++) {
int strInt = [strBefor characterAtIndex:i];
Byte b =  (Byte) ((0xff & strInt) );//( Byte) 0xff&iByte;
bt[i] = b;
}
return bt;
}

直戳demo源码

上一篇下一篇

猜你喜欢

热点阅读