頭文件
//
// BlueToothTool.h
// RuiHan
// 藍牙操作相關工具類
// Created by apple on 2017/2/23.
// Copyright ? 2017年 PGT. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import "DeviceModel.h"
/**
自定義藍牙代理
*/
@PRotocol BlueToothDelegate <NSObject>
/**
藍牙狀態變化
*/
- (void)centralManagerDidUpdateState:(CBManagerState) state;
/**
發現新設備
*/
- (void)didDiscoverPeripheral:(DeviceModel *) device;
/**
* 連接外設進度回調
*/
- (void)connectPeripheralProgress:(float) progress;
/**
* 連接外設成功
*/
- (void)didConnectPeripheral;
@end
@interface BlueToothTool :NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (retain,nonatomic)CBCentralManager *centralManger;//中心管理器
@property (weak,nonatomic)id<BlueToothDelegate> delegate;//回調協議
@property (copy,nonatomic)NSString *tagDeviceMac;//指定設備連接
/**
搜索設備
*/
- (void) scanForPeripheralsWithServices;
/**
連接設備
*/
- (void) connectPeripheral:(CBPeripheral *) peripheral;
//寫數據
-(void)writeChar;
@end
實現文件
//
// BlueToothTool.m
// RuiHan
//
// Created by apple on 2017/2/23.
// Copyright ? 2017年 PGT. All rights reserved.
//
#import "BlueToothTool.h"
@interface BlueToothTool()
//@property (retain,nonatomic) CBPeripheralManager *peripheralManager;//外圍設備管理器
@property (retain,nonatomic) NSMutableArray *peripheralArr;//外部設備數組
@property (retain,nonatomic) CBPeripheral *currentPeripheral;//當前連接設備
@property (retain,nonatomic) CBCharacteristic *readCharacteristic;//當前設備讀取協議
@property (retain,nonatomic) CBCharacteristic *writeCharacteristic;//當前設備寫入協議
@property (retain,nonatomic) NSMutableData *reciveData;//接收數據對象
@end
@implementation BlueToothTool
- (id) init{
if(self = [super init]){
}
returnself;
}
/**
搜索設備
*/
- (void) scanForPeripheralsWithServices{
_peripheralArr = [[NSMutableArray alloc] init];
if(self.delegate && [self.delegate respondsToSelector:@selector(connectPeripheralProgress:)]){
//搜索設備,回調進度
[self.delegateconnectPeripheralProgress:0.1];
}
if(!self.centralManger){
self.centralManger = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}else{
[self stop];
if ([self.centralManger state] == CBCentralManagerStatePoweredOn) {
[self.centralManger scanForPeripheralsWithServices:nil options:nil];
}
}
}
/**
連接設備
*/
- (void) connectPeripheral:(CBPeripheral *) peripheral{
peripheral.delegate = self;
[self.centralManger connectPeripheral:peripheral options:nil];
}
#pragma 藍牙掃描與連接
/**
* 掃描外部設備
* scanForPeripheralsWithServices :如果傳入指定的數組,那么就只會掃描數組中對應ID的設備
* 如果傳入nil,那么就是掃描所有可以發現的設備
* 掃描完外部設備就會通知CBCentralManager的代理
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if ([central state] == CBCentralManagerStatePoweredOn) {
[self.centralManger scanForPeripheralsWithServices:nil options:nil];
// [self.centralManger scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"00001524-1212-EFDE-1523-785FEABCD123"]] options:nil];
}
}
/**
* 發現外部設備,每發現一個就會調用這個方法
* 所以可以使用一個數組來存儲每次掃描完成的數組
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData rssI:(NSNumber *)RSSI
{
// 有可能會導致重復添加掃描到的外設
// 所以需要先判斷數組中是否包含這個外設
if(![_peripheralArr containsObject:peripheral] && peripheral.name !=nil){
[_peripheralArr addObject:peripheral];
NSLog(@"new device:%@,%@",peripheral.identifier.UUIDString,advertisementData);
NSData *data = advertisementData[@"kCBAdvDataManufacturerData"];
if (data && data.length >= 3) {
//mac = [mac stringByReplacingOccurrencesOfString:@" " withString:@""];
long num= data.length;
unsignedchar *recData = malloc(num);
[data getBytes:recData];
NSMutableString *mac = [NSMutableString string];
for (int i = 0; i < num; i++) {
if (i != num-1) {
[mac appendString:[NSString stringWithFormat:@"%02x:",recData[i]]];
}else{
[mac appendString:[NSString stringWithFormat:@"%02x",recData[i]]];
}
}
NSUserDefaults *Userdefaults = [[NSUserDefaults alloc] init];
NSString *bandMac = [Userdefaults objectForKey:@"CURRENTMAC"];
// if (bandMac == nil && ![bandMac isEqualToString:mac]) {
// return;
// }
DeviceModel *device = [[DeviceModel alloc] init];
device.deviceName = peripheral.name;
device.peripheral = peripheral;
device.rssi = [RSSI intValue];
device.macAddress = [mac uppercaseString];
NSLog(@"mac:%@",device.macAddress);
//回調刷新(搜索連接)
if(self.delegate && [self.delegate respondsToSelector:@selector(didDiscoverPeripheral:)]){
[self.delegate didDiscoverPeripheral:device];
//二維碼
}elseif(self.delegate && [self.delegate respondsToSelector:@selector(connectPeripheralProgress:)]){
if(self.tagDeviceMac && [device.macAddress isEqualToString:self.tagDeviceMac]){
//匹配到設備,停止掃描
[self.centralManger stopScan];
//發現指定設備并連接,回調進度
[self.delegate connectPeripheralProgress:0.3];
//自動連接
[self connectPeripheral:peripheral];
}
}
if (recData) {
free(recData);
}
}
/*
DeviceModel *device = [[DeviceModel alloc] init];
device.deviceName = peripheral.name;
device.peripheral = peripheral;
device.rssi = [RSSI intValue];
device.macAddress = [self getMacString:data];
//回調刷新(搜索連接)
if(self.delegate && [self.delegate respondsToSelector:@selector(didDiscoverPeripheral:)]){
[self.delegate didDiscoverPeripheral:device];
//二維碼
}else if(self.delegate && [self.delegate respondsToSelector:@selector(connectPeripheralProgress:)]){
if(self.tagDeviceMac && [device.macAddress isEqualToString:self.tagDeviceMac]){
//匹配到設備,停止掃描
[self.centralManger stopScan];
//發現指定設備并連接,回調進度
[self.delegate connectPeripheralProgress:0.3];
//自動連接
[self connectPeripheral:peripheral];
}
}
*/
}
}
/**
* 斷開連接
*/
- (void)stop
{
[self.centralManger stopScan];
// 斷開所有連接上的外設
for (CBPeripheral *perin _peripheralArr) {
[self.centralManger cancelPeripheralConnection:per];
}
}
/**
* 連接外設成功調用
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
if(self.tagDeviceMac &&self.delegate && [self.delegate respondsToSelector:@selector(connectPeripheralProgress:)]){
//成功連接設備,回調進度
[self.delegate connectPeripheralProgress:0.5];
}
_currentPeripheral = peripheral;
// 查找外設服務
[peripheral discoverServices:nil];
}
/**
連接外設失敗
*/
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(@"%@",error);
}
/**
* 發現服務就會調用代理方法
*
* @param peripheral 外設
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if(self.tagDeviceMac &&self.delegate && [self.delegate respondsToSelector:@selector(connectPeripheralProgress:)]){
//發現服務,回調進度
[self.delegate connectPeripheralProgress:0.6];
}
// 掃描到設備的所有服務
NSArray *services = peripheral.services;
// 根據服務再次掃描每個服務對應的特征
for (CBService *sesin services) {
[peripheral discoverCharacteristics:nil forService:ses];
}
}
/**
* 發現服務對應的特征
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// 服務對應的特征
NSArray *ctcs = service.characteristics;
BOOL foundService =NO;
// 遍歷所有的特征
for (CBCharacteristic *characterin ctcs) {
NSLog(@"uuid:%@",character.UUID.UUIDString);
[_currentPeripheral readValueForCharacteristic:character];
[_currentPeripheral setNotifyValue:YES forCharacteristic:character];
[_currentPeripheral discoverDescriptorsForCharacteristic:character];
// 根據特征的唯一標示過濾
if ([character.UUID.UUIDString isEqualToString:@"0783B03E-8535-B5A0-7140-A304D2495CB8"]) {
//保存讀取協議
_readCharacteristic = character;
//0783B03E-8535-B5A0-7140-A304D2495CBA
}elseif ([character.UUID.UUIDString isEqualToString:@"00001532-1212-EFDE-1523-785FEABCD123"]) {
//保存寫入協議
_writeCharacteristic = character;
}elseif([character.UUID.UUIDString isEqualToString:@"0783B03E-8535-B5A0-7140-A304D2495CB9"]){
//流協議,暫不處理
}
foundService = YES;
}
//發現可用服務后回調刷新
if(foundService &&self.delegate && [self.delegate respondsToSelector:@selector(didConnectPeripheral)]){
[self.delegate didConnectPeripheral];
}else if(self.tagDeviceMac &&self.delegate && [self.delegate respondsToSelector:@selector(connectPeripheralProgress:)]){
//發現可用服務,回調進度
[self.delegate connectPeripheralProgress:1];
}
}
//寫數據
-(void)writeChar
{
char Timer[8] ={0,1,2,3,4,5,6,7};
NSData *TimerData = [[NSData alloc] initWithBytes:Timer length:sizeof(Timer)];
uint16_t val = 0;
NSData * valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
// for ( CBService *service in _currentPeripheral.services ) {
//
// for ( CBCharacteristic *characteristic in service.characteristics ) {
//
// if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"0783B03E-8535-B5A0-7140-A304D2495CBA"]]) {
// NSLog(@"Characteristic %@ value={%@}",characteristic.UUID,characteristic.value);
//
// [_currentPeripheral writeValue:TimerData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
// }
// }
// }
[_currentPeripheral writeValue:TimerData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
// NSLog(@"%@;%@",_currentPeripheral,_writeCharacteristic);
}
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
BOOL Succussed =YES;
if (error) {
Succussed = NO;
NSLog(@" Write error={%@}/n",error);
}
NSLog(@"Finish Write/n");
}
//監聽設備
-(void)startSubscribe
{
[_currentPeripheral setNotifyValue:YES forCharacteristic:_readCharacteristic];
}
-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//按下藍牙裝置的按鍵在這里收不到任何東西
//這部份都會得到Error = Error Domain=CBErrorDomain Code=0 "Unknown error." UserInfo=0x15555ae0 {NSLocalizedDescription=Unknown error.}
NSLog(@"Notifity = %d,error:%@",characteristic.isNotifying,error);//這邊打印出來的值除了2A19的電源打印出來是1,其他都是0。
if (error==nil) {
[peripheral readValueForCharacteristic:characteristic];
}
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSLog(@"recive data:%@",characteristic);
if (!error) {
// NSLog(@"==lenght={%d}=UUId=={%@}==properties={%x}=/n",[characteristic.value length],characteristic.UUID,characteristic.properties);
int length = [characteristic.value length];
unsignedchar *RecData = malloc([characteristic.value length]);
[characteristic.value getBytes:RecData];
int bit0 = RecData[0]&(0x01);
int bit1 = (RecData[0]&(1<<0x01))>>1;
int bit2 = (RecData[0]&(2<<0x01))>>2;
if (RecData) {
free(RecData);
}
}
else {
//NSLog(@"Error didUpdateValueForCharacteristic : %@",error);
}
}
//掃描Descriptors
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
for (CBDescriptor * descriptorin characteristic.descriptors) {
NSLog(@"descriptor: %@",descriptor);
[peripheral readValueForDescriptor:descriptor];
}
}
//獲取Descriptors的值
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error
{
NSLog(@"Descriptors UUID: %@ value: %@",descriptor.UUID,[NSString stringWithFormat:@"%@",descriptor.value]);
NSLog(@"已經向外設%@的特征值%@寫入數據",peripheral.name,_readCharacteristic);
}
@end
新聞熱點
疑難解答