1、首先先对蓝牙状态的一种识别,使用ENUM进行状态判别,分别使用<span style="font-family: Arial, Helvetica, sans-serif;">BluetoothState表示蓝牙连接状态和</span><span style="font-family: Arial, Helvetica, sans-serif;">BluetoothFailState表示蓝牙连接失败的状态,对BluetoothState和BluetoothFailState设置成全局变量,如下方所示</span>
</pre><pre name="code" class="objc">typedef NS_ENUM(NSInteger, BluetoothState){
BluetoothStateDisconnect = 0,
BluetoothStateScanSuccess,
BluetoothStateScaning,
BluetoothStateConnected,
BluetoothStateConnecting
};
typedef NS_ENUM(NSInteger, BluetoothFailState){
BluetoothFailStateUnExit = 0,
BluetoothFailStateUnKnow,
BluetoothFailStateByHW,
BluetoothFailStateByOff,
BluetoothFailStateUnauthorized,
BluetoothFailStateByTimeout
};
</pre><p>2、在连接界面,如<span style="font-family:Menlo; font-size:18px">IsConnectBleViewController,在.h文件中定义</span></p><p><span style="font-family:Menlo; font-size:18px"></span></p><p style="margin-top:0px; margin-bottom:0px; font-size:18px; line-height:normal; font-family:Menlo"></p><pre name="code" class="objc">@property (strong, nonatomic) CBCentralManager * centralManager;
@property (strong, nonatomic) CBPeripheral * discoveredPeripheral;
@property (strong, nonatomic) CBCharacteristic * writeCharachter;
在IsConnectBleViewController.m文件中
//蓝牙状态 -- self.seachRssultLabel为文本提示
- (void)bleState
{
if (bluetoothFailState == BluetoothFailStateUnExit) {
switch (bluetoothState) {
case BluetoothStateConnected:
self.searchResultLabel.text =[NSString stringWithFormat:@"%@",NSLocalizedString(@"已连接", nil)];
break;
case BluetoothStateConnecting:
self.searchResultLabel.text = NSLocalizedString(@"连接中......", nil);
break;
case BluetoothStateDisconnect:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙已断开", nil);
break;
case BluetoothStateScanSuccess:
self.searchResultLabel.text = NSLocalizedString(@"搜索成功,请选择你需要连接的蓝牙设备", nil);
break;
case BluetoothStateScaning:
self.searchResultLabel.text = NSLocalizedString(@"搜索中", nil);
break;
default:
break;
}
}else {
switch (bluetoothFailState) {
case BluetoothFailStateByHW:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙硬件不支持", nil);
break;
case BluetoothFailStateByOff:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙关闭了", nil);
break;
case BluetoothFailStateByTimeout:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙连接超时", nil);
break;
case BluetoothFailStateUnauthorized:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙连接失败", nil);
break;
case BluetoothFailStateUnKnow:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙连接错误", nil);
break;
case BluetoothFailStateUnExit:
self.searchResultLabel.text = NSLocalizedString(@"蓝牙连接中...", nil);
break;
default:
break;
}
}
}
-------- 搜索蓝牙的办法 -----
[self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @NO}];//搜索所有的蓝牙服务
self.centralManager.delegate = self;//必须遵循代理
bluetoothState = BluetoothStateScaning;//蓝牙状态变为搜索状态
[self bleState];
[self performSelector:@selector(searchBluetoothJumpTimeOut) withObject:nil afterDelay:10];//10表示搜索时间,10秒没有搜索到即定义为连接超时
#pragma mark - 蓝牙连接超时的方法
- (void)searchBluetoothJumpTimeOut
{
if (bluetoothState == BluetoothStateScaning) {
bluetoothFailState = BluetoothFailStateByTimeout;
[self ScanBle];//超时之后 -- 的操作,如果不需要超时后继续连接,则不需要这部步
self.searchResultLabel.text = NSLocalizedString(@"蓝牙连接超时,请重新搜索", nil);
}
}
#pragma mark - 搜索蓝牙
-(void)ScanBle{
if(bluetoothFailState == BluetoothFailStateByTimeout){//连接超时
[self.centralManager scanForPeripheralsWithServices:nil
options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @NO }];
self.searchResultLabel.text = NSLocalizedString(@"正在搜索您的设备,请稍等...", nil);
bluetoothState = BluetoothStateScaning;//蓝牙状态变化成可搜索状态
[self bleState];//蓝牙的状态
[self performSelector:@selector(searchBluetoothJumpTimeOut) withObject:nil afterDelay:10];//如果连接超时
}
if(bluetoothFailState==BluetoothFailStateByOff){
self.promptLab.text= NSLocalizedString(@"检查您的蓝牙是否开启后重试", nil);//如果蓝牙设备关闭,提示打开蓝牙设备 -- 弹出视图提示
[self showPromptLab];
}
}
#pragma mark CBCentralManagerDelegate --- 中心设备(手机)的代理方法,即上面定义的 self.centralManager.delegate = self;//必须遵循代理
监控手机的蓝牙状态,一旦蓝牙被关闭可提醒
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (central.state != CBCentralManagerStatePoweredOn) {//end to do
// In a real app, you'd deal with all the states correctly
NSLog(@"fail, state is off.");
switch (central.state) {
case CBCentralManagerStatePoweredOff:
self.searchResultLabel.text = NSLocalizedString(@"连接失败了,请您再检查一下您的手机蓝牙是否开启,然后再试一次吧", nil);
bluetoothFailState = BluetoothFailStateByOff;
break;
case CBCentralManagerStateResetting:
bluetoothFailState=BluetoothFailStateByTimeout;
break;
case CBCentralManagerStateUnsupported:
self.searchResultLabel.text = NSLocalizedString(@"检测到您的手机不支持蓝牙4.0,所以建立不了连接.建议更换您的手机再试试。", nil);
bluetoothFailState = BluetoothFailStateByHW;
break;
case CBCentralManagerStateUnauthorized:
self.searchResultLabel.text = NSLocalizedString(@"连接失败了,请您再检查一下您的手机蓝牙是否开启,然后再试一次吧", nil);
bluetoothFailState = BluetoothFailStateUnauthorized;
break;
case CBCentralManagerStateUnknown:
bluetoothFailState = BluetoothFailStateUnKnow;
self.searchResultLabel.text = @"";
break;
default:
break;
}
return;
}
self.searchResultLabel.text = NSLocalizedString(@"蓝牙已经开启!点击开始搜索连接你的设备", nil);
bluetoothFailState = BluetoothFailStateUnExit;
}
/*
中心设备扫描外围设备
*/
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
if (peripheral == nil||peripheral.identifier == nil/*||peripheral.name == nil*/) {
return;
}
/*
蓝牙列表去重,防止重复的出现 --- 将 外围设备添加到数组中,主要针对多选,一对一可设置self.isConnectMuArra变成一个全局的peripheral
*/
NSMutableArray * repetitionMuArray = [[NSMutableArray alloc]init];
[repetitionMuArray addObject:peripheral];
for (unsigned i = 0; i < repetitionMuArray.count; i++) {
if ([self.isConnectMuArray containsObject:[repetitionMuArray objectAtIndex:i]] == NO) {
[self.isConnectMuArray addObject:[repetitionMuArray objectAtIndex:i]];
}
}
//搜索成功后,修改蓝牙状态
bluetoothFailState = BluetoothFailStateUnExit;
bluetoothState = BluetoothStateScanSuccess;//蓝牙状态为搜索成功
[self bleState];//中心设备状态实时监控
//输出广播名
NSString *CBName1=[advertisementData valueForKeyPath:CBAdvertisementDataLocalNameKey];
NSLog(@"广播名1:%@",CBName1);
}
3、扫描设备成功后进行连接
for (int i = 0; i < self.isConnectMuArray.count ; i++) {
CBPeripheral * selectPeripheral = self.isConnectMuArray[i];
[self.centralManager connectPeripheral:selectPeripheral options:@{CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES}];
}
连接之后执行连接的代理方法
#pragma mark - 已经连接蓝牙设备
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
[self.centralManager stopScan];//连接成功后停止搜索
bluetoothState=BluetoothStateConnected;
[self bleState];
//discoveredPeripheral是全部变量 多连接是否需要创建数组?
discoveredPeripheral=peripheral; /---- 前面所说如果是需要一对一创建全局变量 ----- 如果一对多,则选择下面一步添加数组/
discoveredPeripheral.delegate = self;
[(sysDege).discoverPeripheralArray addObject:peripheral];//(sysDege).discoverPeripheralArray是全局数组
[peripheral discoverServices:@[[CBUUID UUIDWithString:UUID_SERVICE]]];//设置扫描 -- 外围设备扫描自己的服务 UUID_SERVICE是硬件方面的序列号,可为nil
[[NSNotificationCenter defaultCenter]postNotificationName:@"ConnectSuccess" object:nil];//通知成功的消息
}
上一步连接成功外围设备,就开始发送扫描服务的指令,在这里执行扫描到服务的代理办法
#pragma mark - 外围设备已经被发现
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
if (error) {//如果发现错误
NSLog(@"Error discovering services: %@", [error localizedDescription]);
return;
}
NSLog(@"外围设备已被发现peripheral.services%@",peripheral.services);
for (CBService * service in peripheral.services) {
[peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:UUID_CHARACTERISTIC]] forService:service];//扫描到服务就可以发送扫描特性的指令
return;
}
}
#pragma mark - 外围设备扫描到特性
-(void)peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
for (CBCharacteristic * achar in service.characteristics) {
NSLog(@"外围设备Discovered characteristic:CBCharacteristic * achar%@", achar);
NSLog(@"service uuid:%@ characteristics UUID:%@,achar.value:%@",service.UUID,achar.UUID,achar.value);
#pragma mark - 扫描到特性后 设置读写
[aPeripheral readValueForCharacteristic:achar];
[aPeripheral setNotifyValue:YES forCharacteristic:achar];//修改通知的状态
//可读写的特性?
if (self.writeCharachter != achar) {
self.writeCharachter = achar;
writeCharachter = achar;
if (self.discoveredPeripheral != aPeripheral) {
self.discoveredPeripheral = aPeripheral;
}
//可以通过不同的UUID进行发送不同的指令
[self writeCommand:data];
}
}
#pragma mark - 写入特性
-(void)writeCommand:(NSData *)data{
NSLog(@"writeCommand:(NSData *)data:%@",data);
// 连接外围设备为空或者蓝牙状态为断开,退出
if (self.discoveredPeripheral == nil||bluetoothState == BluetoothStateDisconnect) {
return;
}
[self.discoveredPeripheral writeValue:data
forCharacteristic:self.writeCharachter
type:CBCharacteristicWriteWithResponse];
NSLog(@"write command is success");
}
//发送指令后可以得到硬件返回的信息
#pragma mark - 特性值变化
- (void) peripheral:(CBPeripheral *)aPeripheral
didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic
error:(NSError *)error
{
NSLog(@"特性回调值:%@",characteristic);
NSString *result = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(@"特性回调值的温度:%@",result);
}
连接不成功 -- 即断开
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
self.discoveredPeripheral = nil;//断开之后为空 -- 一对一的方法,一对多为(sysDege).discoverPeripheralArray数组清空
bluetoothState = BluetoothStateDisconnect;
[self bleState];
self.searchResultLabel.text = NSLocalizedString(@"蓝牙设备已经断开了,请重新搜索", nil);
[[NSNotificationCenter defaultCenter]postNotificationName:@"bleDis" object:nil];//发送蓝牙断开的通知
}
蓝牙发送数据 -- self.discoveredPeripheral表示外围设备 -- self.writeCharachter表示特性
[self.discoveredPeripheral writeValue:data
forCharacteristic:self.writeCharachter
type:CBCharacteristicWriteWithResponse];