2019独角兽企业重金招聘Python工程师标准>>>
蓝牙功能
作为蓝牙中心,连接外设
一般性的步骤是先扫描设备,然后根据蓝牙设备的名称等信息找到需要连接的设备,进行连接
然后获取设备的服务,可以订阅对应的服务,可以对设备进行写入
//
// ViewController.m
// BlueTooth
//
// Created by JackXu on 15/6/9.
// Copyright (c) 2015年 BFMobile. All rights reserved.
//#import "ViewController.h"
#define MyDeviceName @"HMSoft"
@interface ViewController ()@property (nonatomic, strong) CBCentralManager *centralMgr;
@property (nonatomic, strong) CBPeripheral *discoveredPeripheral;
@property (nonatomic, strong) CBCharacteristic *writeCharacteristic;@property (nonatomic,strong) CBCharacteristic *testCharacteristic;
@property (weak, nonatomic) IBOutlet UITextField *editText;
@property (weak, nonatomic) IBOutlet UILabel *resultText;@property (nonatomic,strong) CBPeripheral *smartWatchPeripheral;
@property (nonatomic,strong) NSMutableArray *discoveredPerpheralArray;@property (nonatomic,strong) CBService *testService;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.centralMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}//检查App的设备BLE是否可用 (ensure that Bluetooth low energy is supported and available to use on the central device)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{switch (central.state){case CBCentralManagerStatePoweredOn://discover what peripheral devices are available for your app to connect to//第一个参数为CBUUID的数组,需要搜索特点服务的蓝牙设备,只要每搜索到一个符合条件的蓝牙设备都会调用didDiscoverPeripheral代理方法[self.centralMgr 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
{NSLog(@"peripheral == %@ rssi == %@",peripheral,RSSI);//找到需要的蓝牙设备,停止搜素,保存数据if([peripheral.name isEqualToString:MyDeviceName]){_discoveredPeripheral = peripheral;[_centralMgr connectPeripheral:peripheral options:nil];}for ( CBPeripheral *savedPeripheral in self.discoveredPerpheralArray) {if (![[savedPeripheral.identifier UUIDString] isEqualToString:[peripheral.identifier UUIDString]]) {// self.discoveredPerpheralArray }}NSString *peripheralName = peripheral.name;NSRange wannaFitLocation = [peripheralName rangeOfString:@"WannaFit"];if (wannaFitLocation.location != NSNotFound){self.smartWatchPeripheral = peripheral;[_centralMgr connectPeripheral:peripheral options:nil];}}- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{NSLog(@"didDisconnectPeripheral %s",__FUNCTION__);
}//连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{NSLog(@"didConnectPeripheral %s",__FUNCTION__);//Before you begin interacting with the peripheral, you should set the peripheral’s delegate to ensure that it receives the appropriate callbacks(设置代理)[_discoveredPeripheral setDelegate:self];//discover all of the services that a peripheral offers,搜索服务,回调didDiscoverServices[_discoveredPeripheral discoverServices:nil];[self.smartWatchPeripheral setDelegate:self];[self.smartWatchPeripheral discoverServices:nil];
}//连接失败,就会得到回调:
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{//此时连接发生错误NSLog(@"connected periphheral failed");
}//获取服务后的回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{if (error){NSLog(@"didDiscoverServices : %@", [error localizedDescription]);return;}for (CBService *s in peripheral.services){NSLog(@"Service found with UUID : %@", s.UUID);//Discovering all of the characteristics of a service,回调didDiscoverCharacteristicsForService[s.peripheral discoverCharacteristics:nil forService:s];}
}//获取特征后的回调
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{if (error){NSLog(@"didDiscoverCharacteristicsForService error : %@", [error localizedDescription]);return;}NSLog(@"service == %@",service);for (CBCharacteristic *c in service.characteristics){NSLog(@"c.properties:%lu",(unsigned long)c.properties) ;//Subscribing to a Characteristic’s Value 订阅NSLog(@"characteristic == %@",c);[peripheral setNotifyValue:YES forCharacteristic:c];// read the characteristic’s value,回调didUpdateValueForCharacteristic[peripheral readValueForCharacteristic:c];_writeCharacteristic = c;}}//订阅的特征值有新的数据时回调
- (void)peripheral:(CBPeripheral *)peripheral
didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristicerror:(NSError *)error {if (error) {NSLog(@"Error changing notification state: %@",[error localizedDescription]);}[peripheral readValueForCharacteristic:characteristic];}- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{NSLog(@"characteristic value == %@",characteristic.value);if (error){NSLog(@"didUpdateValueForCharacteristic error : %@", error.localizedDescription);return;}NSData *data = characteristic.value;_resultText.text = [[ NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];NSLog(@"characteristic properties == %lu value == %@ ",(unsigned long)characteristic.properties,characteristic.value);// NSLog(@"hex string == %@",[self convertDataToHexStr:data]);
//
//}- (NSMutableArray *)discoveredPerpheralArray{if (!_discoveredPerpheralArray) {_discoveredPerpheralArray = [NSMutableArray array];}return _discoveredPerpheralArray;}#pragma mark 写数据
-(void)writeChar:(NSData *)data
{//回调didWriteValueForCharacteristic[_discoveredPeripheral writeValue:data forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];NSData *data2 = [self test2Data];NSLog(@"data2 == %@",data2);for (CBService *service in self.smartWatchPeripheral.services) {for (CBCharacteristic *characteristic in service.characteristics) {[self.smartWatchPeripheral writeValue:data2 forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];[self.smartWatchPeripheral writeValue:data2 forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];}}}//搜索到Characteristic的Descriptors
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{//打印出Characteristic和他的DescriptorsNSLog(@"characteristic uuid:%@",characteristic.UUID);for (CBDescriptor *d in characteristic.descriptors) {NSLog(@"Descriptor uuid:%@",d.UUID);}}
//获取到Descriptors的值
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{//打印出DescriptorsUUID 和value//这个descriptor都是对于characteristic的描述,一般都是字符串,所以这里我们转换成字符串去解析NSLog(@"characteristic uuid:%@ value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value);
}#pragma mark 写数据后回调
- (void)peripheral:(CBPeripheral *)peripheral
didWriteValueForCharacteristic:(CBCharacteristic *)characteristicerror:(NSError *)error {if (error) {NSLog(@"Error writing characteristic value: %@",[error localizedDescription]);return;}NSLog(@"写入%@成功",characteristic);
}#pragma mark 发送按钮点击事件
- (IBAction)sendClick:(id)sender {// 字符串转DataNSData *data =[_editText.text dataUsingEncoding:NSUTF8StringEncoding];[self writeChar:data];
}- (NSString *)convertDataToHexStr:(NSData *)data {if (!data || [data length] == 0) {return @"";}NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];[data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {unsigned char *dataBytes = (unsigned char*)bytes;for (NSInteger i = 0; i < byteRange.length; i++) {NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];if ([hexStr length] == 2) {[string appendString:hexStr];} else {[string appendFormat:@"0%@", hexStr];}}}];return string;
}- (NSData *)convertHexStrToData:(NSString *)str {if (!str || [str length] == 0) {return nil;}NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];NSRange range;if ([str length] % 2 == 0) {range = NSMakeRange(0, 2);} else {range = NSMakeRange(0, 1);}for (NSInteger i = range.location; i < [str length]; i += 2) {unsigned int anInt;NSString *hexCharStr = [str substringWithRange:range];NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];[scanner scanHexInt:&anInt];NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];[hexData appendData:entity];range.location += range.length;range.length = 2;}return hexData;
}- (NSData *)test1Data{Byte bytes[20] = {0x89,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9A};NSData *data2 = [NSData dataWithBytes:bytes length:20];return data2;}
- (NSData *)test2Data{Byte bytes[20] = {0xA5,0x11,0x00,0x00,0x02,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC2};NSData *data2 = [NSData dataWithBytes:bytes length:20];return data2;}- (NSData *)setWatchTime{Byte bytes[10] = {0x08,0x14,0x0e,0x0a,0x1f,0x0f,0x38,0x1e,0x01,0x00};Byte resultByte = 0x00;for (int i = 0; i<9; i++) {resultByte += bytes[i];}NSLog(@"result bye == %x",resultByte);resultByte = resultByte & 0xff;NSLog(@"result bye == %x",resultByte);bytes[9] = resultByte;NSData *data2 = [NSData dataWithBytes:bytes length:10];NSLog(@"data2 == %@",data2);return data2;}- (NSData *)getWatchInfo{Byte bytes[10] = {0xF6,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00};Byte resultByte = 0x00;for (int i = 0; i<9; i++) {resultByte += bytes[i];}NSLog(@"result bye == %x",resultByte);resultByte = resultByte & 0xff;NSLog(@"result bye == %x",resultByte);bytes[9] = resultByte;NSData *data2 = [NSData dataWithBytes:bytes length:10];NSLog(@"data2 == %@",data2);return data2;
}- (NSData *)findTheWatch{Byte bytes[10] = {0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00};Byte resultByte = 0x00;for (int i = 0; i<9; i++) {resultByte += bytes[i];}resultByte = resultByte & 0xff;bytes[9] = resultByte;NSData *data2 = [NSData dataWithBytes:bytes length:10];NSLog(@"data2 == %@",data2);return data2;
}
@end
作为蓝牙设备
#import "BePeripheralViewController.h"static NSString *const ServiceUUID1 = @"FFF0";
static NSString *const notiyCharacteristicUUID = @"FFF1";
static NSString *const readwriteCharacteristicUUID = @"FFF2";
static NSString *const ServiceUUID2 = @"FFE0";
static NSString *const readCharacteristicUUID = @"FFE1";
static NSString *const localTimeUUID = @"Local Time Information";static NSString * const LocalNameKey = @"WannaFit-T10D-5F29";@implementation BePeripheralViewController{CBPeripheralManager *peripheralManager;//定时器NSTimer *timer;//添加成功的service数量int serviceNum;UILabel *info;}
- (void)viewDidLoad {[super viewDidLoad];/*和CBCentralManager类似,蓝牙设备打开需要一定时间,打开成功后会进入委托方法- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;模拟器永远也不会得CBPeripheralManagerStatePoweredOn状态*/peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];//页面样式[self.view setBackgroundColor:[UIColor whiteColor]];info = [[UILabel alloc]initWithFrame:self.view.frame];[info setText:@"正在打开设备"];[info setTextAlignment:NSTextAlignmentCenter];[self.view addSubview:info];}- (void)viewWillDisappear:(BOOL)animated
{[super viewWillDisappear:animated];[peripheralManager stopAdvertising];
}//配置bluetooch的
-(void)setUp{//characteristics字段描述CBUUID *CBUUIDCharacteristicUserDescriptionStringUUID = [CBUUID UUIDWithString:CBUUIDCharacteristicUserDescriptionString];/*可以通知的Characteristicproperties:CBCharacteristicPropertyNotify permissions CBAttributePermissionsReadable*/CBMutableCharacteristic *notiyCharacteristic = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:notiyCharacteristicUUID] properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];/*可读写的characteristicsproperties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyReadpermissions CBAttributePermissionsReadable | CBAttributePermissionsWriteable*/CBMutableCharacteristic *readwriteCharacteristic = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:readwriteCharacteristicUUID] properties:CBCharacteristicPropertyWrite | CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable | CBAttributePermissionsWriteable];//设置descriptionCBMutableDescriptor *readwriteCharacteristicDescription1 = [[CBMutableDescriptor alloc]initWithType: CBUUIDCharacteristicUserDescriptionStringUUID value:@"name"];[readwriteCharacteristic setDescriptors:@[readwriteCharacteristicDescription1]];/*只读的Characteristicproperties:CBCharacteristicPropertyReadpermissions CBAttributePermissionsReadable*/CBMutableCharacteristic *readCharacteristic = [[CBMutableCharacteristic alloc]initWithType:[CBUUID UUIDWithString:readCharacteristicUUID] properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable];//service1初始化并加入两个characteristicsCBMutableService *service1 = [[CBMutableService alloc]initWithType:[CBUUID UUIDWithString:ServiceUUID1] primary:YES];NSLog(@"%@",service1.UUID);[service1 setCharacteristics:@[notiyCharacteristic,readwriteCharacteristic]];//service2初始化并加入一个characteristicsCBMutableService *service2 = [[CBMutableService alloc]initWithType:[CBUUID UUIDWithString:ServiceUUID2] primary:YES];[service2 setCharacteristics:@[readCharacteristic]];//添加后就会调用代理的- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error[peripheralManager addService:service1];[peripheralManager addService:service2];
}#pragma mark -- CBPeripheralManagerDelegate//peripheralManager状态改变
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{switch (peripheral.state) {//在这里判断蓝牙设别的状态 当开启了则可调用 setUp方法(自定义)case CBPeripheralManagerStatePoweredOn:NSLog(@"powered on");[info setText:[NSString stringWithFormat:@"设备名%@已经打开,可以使用center进行连接",LocalNameKey]];[self setUp];break;case CBPeripheralManagerStatePoweredOff:NSLog(@"powered off");[info setText:@"powered off"];break;default:break;}
}//perihpheral添加了service
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{if (error == nil) {serviceNum++;}//因为我们添加了2个服务,所以想两次都添加完成后才去发送广播if (serviceNum==2) {//添加服务后可以在此向外界发出通告 调用完这个方法后会调用代理的//(void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error[peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:ServiceUUID1],[CBUUID UUIDWithString:ServiceUUID2]],CBAdvertisementDataLocalNameKey : LocalNameKey}];}}//peripheral开始发送advertising
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error{NSLog(@"in peripheralManagerDidStartAdvertisiong");
}//订阅characteristics
-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{NSLog(@"订阅了 %@的数据",characteristic.UUID);//每秒执行一次给主设备发送一个当前时间的秒数timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendData:) userInfo:characteristic repeats:YES];
}//取消订阅characteristics
-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic{NSLog(@"取消订阅 %@的数据",characteristic.UUID);//取消回应[timer invalidate];
}//发送数据,发送当前时间的秒数
-(BOOL)sendData:(NSTimer *)t {CBMutableCharacteristic *characteristic = t.userInfo;NSDateFormatter *dft = [[NSDateFormatter alloc]init];[dft setDateFormat:@"ss"];NSLog(@"%@",[dft stringFromDate:[NSDate date]]);//执行回应Central通知数据return [peripheralManager updateValue:[[dft stringFromDate:[NSDate date]] dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:nil];}//读characteristics请求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{NSLog(@"didReceiveReadRequest");NSLog(@"request == %@ request.value == %@",request,request.value);//判断是否有读数据的权限if (request.characteristic.properties & CBCharacteristicPropertyRead) {NSData *data = request.characteristic.value;[request setValue:data];//对请求作出成功响应[peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];}else{[peripheralManager respondToRequest:request withResult:CBATTErrorWriteNotPermitted];}
}//写characteristics请求
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests{NSLog(@"didReceiveWriteRequests");CBATTRequest *request = requests[0];//判断是否有写数据的权限if (request.characteristic.properties & CBCharacteristicPropertyWrite) {//需要转换成CBMutableCharacteristic对象才能进行写值CBMutableCharacteristic *c =(CBMutableCharacteristic *)request.characteristic;c.value = request.value;[peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];}else{[peripheralManager respondToRequest:request withResult:CBATTErrorWriteNotPermitted];}}//
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral{NSLog(@"peripheralManagerIsReadyToUpdateSubscribers");}@end
更进一步的蓝牙功能
https://my.oschina.net/u/2340880/blog/644432
https://github.com/ZYHshao/BlueGame
参考资料
iOS简易蓝牙对战五子棋游戏设计思路之一——核心蓝牙通讯类的设计
https://my.oschina.net/u/2340880/blog/644432
ios蓝牙开发(二)ios连接外设的代码实现
http://liuyanwei.jumppo.com/2015/08/14/ios-BLE-2.html
iOS-BLE蓝牙开发持续更新
http://www.jianshu.com/p/84b5b834b942
刘彦玮的技术博客中文章对应的demo http://liuyanwei.jumppo.com http://liuyanwei.jumppo.com
https://github.com/coolnameismy/demo
转载于:https://my.oschina.net/u/2360054/blog/751036