记录下蓝牙开发:
先明确5个概念:
CBCentral 中心设备(蓝牙主机)
CBPeripheral 外设(蓝牙从机)
CBService 服务
CBCharacteristic 特征
CBUUID UUID
蓝牙连接的步骤就是建立中心设备,扫描外设,按硬件话说就是主机找从机。在外设中找到服务,在服务里找到它所有的特征。
写了个BluetoothHelper,注释已经写的很清楚了。
BluetoothHelper.h
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
@interface BluetoothHelper : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
+ (BluetoothHelper *)sharedInstance;
- (void)connect;
- (void)disConnect;
- (void)sendData:(NSString *)command;
@end
BluetoothHelper.m
#import "BluetoothHelper.h"
#import "ToolHelper.h"
static NSString * const kName = @"BLE_Serial";
static NSString * const kSUUID= @"0003CDD0-XXXX-XXXX-XXXX-00805f9bXXXX";
static NSString * const KNotifyUUID = @"0003CDD1-XXXX-XXXX-XXXX-00805f9bXXXX";
static NSString * const kWriteUUID= @"0003CDD2-XXXX-XXXX-XXXX-00805f9bXXXX";
@interface BluetoothHelper ()
@property (nonatomic, strong) CBCentralManager * manger;
@property (nonatomic, strong) CBPeripheral * cbPeripheral;
@property (nonatomic, assign) BOOL blueIsOn;
@end
@implementation BluetoothHelper
#pragma mark - life cycle
+ (BluetoothHelper *)sharedInstance{
static BluetoothHelper *instance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
instance = [[self alloc] init];
});
return instance;
}
- (instancetype)init{
self = [super init];
if (self) {
self.manger = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
}
return self;
}
#pragma mark - CBCentralManagerDelegate Methods
//检测蓝牙状态
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
switch (central.state) {
case CBCentralManagerStatePoweredOn:{
self.blueIsOn = YES;
}
break;
case CBCentralManagerStateResetting:
case CBCentralManagerStateUnauthorized:
case CBCentralManagerStateUnknown:
case CBCentralManagerStateUnsupported:
case CBCentralManagerStatePoweredOff:{
self.blueIsOn = NO;
}
break;
default:
NSLog(@"Central Manager did change state");
break;
}
}
//发现蓝牙设备
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
//设置监听,以保证始终寻找外设
[self startScanningTimeoutMonitor];
if ([peripheral.name isEqualToString:kName]) {
[self.manger stopScan];
[self.manger connectPeripheral:peripheral options:nil];
self.cbPeripheral = peripheral;
}
NSLog(@"发现蓝牙%@",peripheral);
}
//连接外设成功
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
self.cbPeripheral = peripheral;
self.cbPeripheral.delegate = self;
[self.cbPeripheral discoverServices:@[]];
[self cancelScanningTimeoutMonitor];
[self cancelSendTimeOut];
NSLog(@"连接成功%@",self.cbPeripheral);
}
//连接外设失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
if (error) {
NSLog(@"连接失败ERROR:%@ peripheral:%@",error,peripheral);
}
}
//断开外设连接
-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@"断开连接%@",peripheral);
self.cbPeripheral = nil;
[ToolHelper showErrorMessage:@"连接失败,重新连接"];
[self connect];
}
#pragma mark - CBPeripheralDelegate Methods
//已搜索到services 根据周边找特征
-(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
for (CBService *s in peripheral.services) {
if ([s.UUID isEqual:[CBUUID UUIDWithString:kSUUID]]) {
[peripheral discoverCharacteristics:nil forService:s];
NSLog(@"找到周边peripheral:%@ Service:%@",peripheral,s);
return;
}
}
}
//已搜索到Characteristics 设置订阅
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
for (CBCharacteristic *c in service.characteristics) {
if ([c.UUID isEqual:[CBUUID UUIDWithString:KNotifyUUID]]) {
//设置监听然后会走didUpdateNotificationStateForCharacteristic
[peripheral setNotifyValue:YES forCharacteristic:c];
NSLog(@"设置订阅 peripheral%@ Characteristic%@",peripheral,c);
}
}
}
//注册订阅后的中间通知步骤 判断是否正确
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if (error == nil) {
[peripheral readValueForCharacteristic:characteristic];
}
NSLog(@"设置读取返回数据 peripheral%@ characteristic%@",peripheral,characteristic);
//给外设发送指定字符验证是否联通
[self sendData:@"yue?"];
}
//蓝牙回传的数据都会从这个方法中得到
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if (error) {
NSLog(@"返回数据ERROR:%@",error);
}
NSString * updateString = [[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(@"updateString - %@",updateString);
if ([updateString isEqualToString:@"yue!"]){
[ToolHelper showSuccessMessage:@"成功连接设备"];
} else {
}
}
#pragma mark - private methods
//把要发送的数据用ASCII编码
- (void)sendData:(NSString *)command
{
NSData * data = [command dataUsingEncoding:NSASCIIStringEncoding];
[self writeData:data];
}
//将数据传送给蓝牙
- (void)writeData:(NSData *)bluetoothData{
for (CBService *service in self.cbPeripheral.services ) {
if ([service.UUID isEqual:[CBUUID UUIDWithString:kSUUID]]) {
for ( CBCharacteristic *characteristic in service.characteristics ) {
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kWriteUUID]]) {
/* EVERYTHING IS FOUND, WRITE characteristic ! */
[self.cbPeripheral writeValue:bluetoothData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}
}
}
}
}
#pragma mark - public methods
//寻找外设
- (void)connect{
if (self.blueIsOn) {
NSLog(@"scan....");
if(self.cbPeripheral){
[self.manger connectPeripheral:self.cbPeripheral options:nil];
}else {
[self.manger scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
}
}
[self startSendTimeOut];
}
//断开蓝牙连接
- (void)disConnect{
if (self.cbPeripheral) {
[self.manger cancelPeripheralConnection:self.cbPeripheral];
[self.manger stopScan];
}
[ToolHelper showErrorMessage:@"发送失败,请重新发送"];
}
#pragma mark - Connection Timeout
- (void)startScanningTimeoutMonitor {
[self cancelScanningTimeoutMonitor];
[self performSelector:@selector(connect)
withObject:nil
afterDelay:2.0f];
}
- (void)cancelScanningTimeoutMonitor {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(connect)
object:nil];
}
- (void)startSendTimeOut {
[self performSelector:@selector(disConnect)
withObject:nil
afterDelay:60.0f];
}
- (void)cancelSendTimeOut {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(disConnect)
object:nil];
}
@end
网友评论