iOS 通過藍牙給設備發(fā)送命令并接收回復信息

#import?<Foundation/Foundation.h>

#import?<CoreBluetooth/CoreBluetooth.h>

NS_ASSUME_NONNULL_BEGIN

#define kCharacteristicTXUUID @""

#define kCharacteristicRXUUID @""

#define kServicesID @""

@protocol EquipmentManagerDelegate <NSObject>

@optional

//發(fā)送命令返回的值

-(void)sendCommandABackWithdictionary:(NSDictionary *)dictionary;

-(void)sendCommandBBackWithdictionary:(NSDictionary *)dictionary;

-(void)sendCommandCBackWithdictionary:(NSDictionary *)dictionary;

-(void)sendCommandDBackWithdictionary:(NSDictionary *)dictionary byte2:(Byte)byte2;

-(void)sendCommandEBackWithdictionary:(NSDictionary *)dictionary;

//發(fā)送abc命令 一個循環(huán)

-(void)sendCommandABCForALoop;

//手機的的藍牙狀態(tài)

-(void)centralManagerDidUpdateWithState:(NSInteger )state;

//掃描到設備

-(void)scanToDeviceWithPeripheral:(CBPeripheral *)peripheral;

//連接失敗

-(void)failedToConnectDeviceWithPeripheral:(CBPeripheral *)peripheral;

@end

@interface EquipmentManager : NSObject

//中心設備管理

@property(nonatomic,strong)CBCentralManager *bluetoothManage;

//外圍設備

@property(nonatomic,strong)CBPeripheral *connectedPeripheral;

@property(nonatomic,strong)CBCharacteristic *characteristicTX;

@property(nonatomic,strong)CBCharacteristic *characteristicRX;

//是否連接

@property(nonatomic,assign)BOOL isConnection;

//命令

@property(nonatomic,strong)NSString *commandStr;

//命令是第幾個

@property(nonatomic,assign)NSInteger commandIndex;

//設備功率 設備編碼

@property(nonatomic,strong)NSArray *powerArr;

//當前設備對應的值

@property(nonatomic,strong)NSDictionary *equipmentData;

@property(nonatomic,weak)id <EquipmentManagerDelegate>delegate;

//掃描到的并存過本地的CBPeripheral 數(shù)組

@property(nonatomic,strong)NSArray *peripheralArray;

+(instancetype)shareCentralManager;

//停止鏈接

- (void)stopConnection;

//清除警告

-(void)clearAlarmWithIndex:(NSInteger)index;

//掃描設備

-(void)scanEquipment;

//停止掃描

-(void)stopScan;

//連接

-(void)connectPeripheralWithPeripheral:(CBPeripheral *)peripheral;

@end

.m文件

#import "EquipmentManager.h"

//#import <Bugly/Bugly.h>

@interface EquipmentManager ()<CBCentralManagerDelegate,CBPeripheralDelegate>

@property(nonatomic,assign)BOOL isManualPause;//手動暫停

@end

@implementation EquipmentManager

static EquipmentManager *_manager = nil;

+(instancetype)shareCentralManager{


? ? static?dispatch_once_toneToken;

? ? ? ? dispatch_once(&oneToken, ^{

? ? ? ? ? ? _manager= [[EquipmentManager alloc]init];

? ? ? ? });

? ? ? ? return_manager;

}

-(instancetype)init{

? ? if(self== [super?init]){

? ? ? ? [self?initData];

? ? }

? ? return self;

}

-(void)initData {

? ? self.bluetoothManage = [[CBCentralManager alloc]initWithDelegate:self queue:nil];



}

//掃描設備

-(void)scanEquipment{

//? ? BLYLogInfo(@"開始掃描設備");

? ? self.bluetoothManage.delegate = self;

? ? [self.bluetoothManage scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];

}

//停止鏈接

- (void)stopConnection

{

? ? self.isManualPause = YES;

? ? if(self.connectedPeripheral){

? ? ? ? [self.bluetoothManage cancelPeripheralConnection:self.connectedPeripheral];

? ? }

? ? self.isConnection = NO;

}

-(void)processingDataAWithdictionary:(NSDictionary*)oldDictionarycharacteristic:(CBCharacteristic*)characteristic{

//dataValue 接收發(fā)送命令的值

? ? NSData*dataValue= characteristic.value;

? ? if(dataValue.length!=17){

?? ? ? return;

?? }

//將返回的data拆分成對應的字符串字節(jié)數(shù)組

? ? NSArray*dataArr = [self?ConvertToNSString:dataValue];

//將dataArr里的字符串轉(zhuǎn)成Byte類型

? ? Byte byte[[dataValue length]];

? ? for(int?i =0; i< dataArr.count; i++) {

? ? ? ? NSString*str = [NSString stringWithFormat:@"0x%@",dataArr[i]];

//? ? ? ? NSLog(@"str===%d=%@",i,str);

? ? ? ? intstr_value;

? ? ? ? char *str_char = [str cStringUsingEncoding:NSASCIIStringEncoding];

? ? ? ? sscanf(str_char,"%x",&str_value);

? ? ? ? byte[i] = str_value;

? ? }

//CRC驗證

? ??if((byte[15] &0xff) != [self?getCrcCode:byte] ){

? ? ? ? return;

? ? }

//處理藍牙發(fā)過來的數(shù)據(jù)處理

? ? NSMutableDictionary *data = [NSMutableDictionary dictionaryWithDictionary:oldDictionary];

? ? self.equipmentData= data;

? ? if(self.delegate&& [self.delegaterespondsToSelector:@selector(sendCommandABackWithdictionary:)]){

? ? ? ? [self.delegate sendCommandABackWithdictionary:data];

? ? }

}


//VC調(diào)用命令后發(fā)送給藍牙

-(void)setCommandStr:(NSString*)commandStr{

? ? _commandStr= commandStr;

? ? [self sendMsgWithSubPackage:_commandStr];

}

//清除警告 向藍牙設備發(fā)送命令

-(void)clearAlarmWithIndex:(NSInteger)index{

//? ? BLYLogInfo(@"clearAlarmWithIndex======%ld",index);

? ? if(!self.characteristicRX){


? ? ? ? return;

? ? }

?Byte byteArr[] = {};

? ? ? ? ? ? NSData*data = [[NSData alloc]initWithBytes:byteArrlength:16];

[self.connectedPeripheral writeValue:data forCharacteristic:self.characteristicRX type:(CBCharacteristicWriteWithResponse)];

}

//停止掃描

-(void)stopScan{

//? ? BLYLogInfo(@"停止掃描");

? ? [self.bluetoothManage stopScan];

}

//連接

-(void)connectPeripheralWithPeripheral:(CBPeripheral *)peripheral{

? ? if(peripheral){

? ? ? ? self.connectedPeripheral= peripheral;

? ? ? ? self.connectedPeripheral.delegate = self;

? ? ? ? NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey];

//? ? ? ? BLYLogInfo(@"連接設備====%@=====UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString);

? ? ? ? //1,連接藍牙

? ? ? ? [self.bluetoothManage connectPeripheral:? self.connectedPeripheral options:options];


? ? }

}

#pragma mark -----CBCentralManagerDelegate

- (void)centralManagerDidUpdateState:(CBCentralManager *)central{

? ? if(self.delegate&& [self.delegaterespondsToSelector:@selector(centralManagerDidUpdateWithState:)]){

? ? ? ? [self.delegate centralManagerDidUpdateWithState:central.state];

? ? }

}

//2.實現(xiàn)已連接外設的回調(diào) 查找服務

-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{


? ? [self.connectedPeripheral discoverServices:nil];

? ? self.isConnection = YES;

? ? self.isManualPause = NO;

? ? NSLog(@"連接成功");

//? ? BLYLogInfo(@"連接成功====%@=====UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString);


}

// 斷開鏈接設備

-(void)centralManager:(CBCentralManager*)centraldidDisconnectPeripheral:(CBPeripheral*)peripheralerror:(NSError*)error{


? ? NSLog(@"斷開連接");

//? ? BLYLogWarn(@"斷開連接====%@=====UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString);

? ? self.connectedPeripheral = nil;

? ? self.isConnection = NO;

? ? if(self.isManualPause == NO){

? ? ? ? if(self.delegate&& [self.delegaterespondsToSelector:@selector(failedToConnectDeviceWithPeripheral:)]){

? ? ? ? ? ? [self.delegate failedToConnectDeviceWithPeripheral:peripheral];

? ? ? ? }

? ? }




}

// 2.1未能連接的處理方法

-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{

? ? NSLog(@"連接失敗=========%@,(%@)",peripheral,[errorlocalizedDescription]);

//? ? BLYLogWarn(@"連接失敗====%@=====UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString);

? ? self.isConnection = NO;

? ? if(self.delegate&& [self.delegaterespondsToSelector:@selector(failedToConnectDeviceWithPeripheral:)]){

? ? ? ? [self.delegate failedToConnectDeviceWithPeripheral:peripheral];

? ? }

}

-(void)centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(CBPeripheral*)peripheraladvertisementData:(NSDictionaryid> *)advertisementDataRSSI:(NSNumber*)RSSI{



? ? if(peripheral.name.length!=0){

//? ? ? ? NSData *data = [advertisementData objectForKey:@"kCBAdvDataManufacturerData"];

//

//? ? ? ? NSString *astr = [self hexadecimalString:data];

//? ? ? ? if(!astr){

//? ? ? ? ? ? return;

//? ? ? ? }

//? ? ? ? BLYLogInfo(@"掃描到設備====%@=====UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString);


? ? ? ? if(self.delegate&& [self.delegaterespondsToSelector:@selector(scanToDeviceWithPeripheral:)]){

? ? ? ? ? ? [self.delegate scanToDeviceWithPeripheral:peripheral];

? ? ? ? }



? ? }



}

#pragma mark -------------------CBPeripheralDelegate

/**

?*? 3.發(fā)現(xiàn)服務就會調(diào)用代理方法

?*

?*? @param peripheral 外設

?*/

-(void)peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error{

? ? // 掃描到設備的所有服務

? ? NSArray*services = peripheral.services;

? ? // 根據(jù)服務再次掃描每個服務對應的特征

? ? for(CBService*sesinservices) {

? ? ? ? if([ses.UUID.UUIDString isEqualToString:kServicesID]){

? ? ? ? ? ? [peripheraldiscoverCharacteristics:nil forService:ses];

? ? ? ? }

? ? }

}

/**

?*? 4.發(fā)現(xiàn)服務對應的特征

?*/

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{

? ? // 服務對應的特征

? ? NSArray*ctcs = service.characteristics;


? ? intcount =0;

? ? // 遍歷所有的特征

? ? for(inti =0; i < ctcs.count;i++) {

? ? ? ? CBCharacteristic*character = ctcs[i];

? ? ? ? // 根據(jù)特征的唯一標示過濾


? ? ? ? if([character.UUID.UUIDString isEqualToString:kCharacteristicRXUUID] ) {



? ? ? ? ? ? self.characteristicRX= character;

? ? ? ? ? ? [self.connectedPeripheral setNotifyValue:YES forCharacteristic:character];



? ? ? ? }

//? ? ? ? BLYLogInfo(@"服務特征===name=%@=====UUIDString=%@====.character.UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString,character.UUID.UUIDString);

? ? ? ? if([character.UUID.UUIDString isEqualToString:kCharacteristicTXUUID]){

? ? ? ? ? ? self.characteristicTX= character;

? ? ? ? ? ? [self.connectedPeripheral setNotifyValue:YES forCharacteristic:character];

//? ? ? ? ? ? BLYLogInfo(@"服務特征正確===name=%@=====UUIDString=%@====.character.UUIDString=%@",peripheral.name,peripheral.identifier.UUIDString,character.UUID.UUIDString);

? ? ? ? ? ? [self sendMsgWithSubPackage:self.commandStr];

? ? ? ? }


? ? ? ? [peripheral discoverDescriptorsForCharacteristic:character];

? ? ? ? count++;

? ? }

? ? if(count == ctcs.count){

? ? ? ? if(self.characteristicTX == nil && self.characteristicRX == nil){

? ? ? ? ? ? [self?stopConnection];

? ? ? ? }

? ? }


}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{

? ? //? ? if(characteristic.isNotifying){

? ? [peripheralreadValueForCharacteristic:characteristic];

? ? //? ? }else{

? ? //? ? ? ? NSLog(@"Notification stopped on %@.? Disconnecting", characteristic);

? ? //? ? ? ? ? ? ? NSLog(@"%@", characteristic);

? ? //? ? ? ? [self.bluetoothManage cancelPeripheralConnection:peripheral];

? ? //? ? }

}

-(void)senderB{


}


#pragma mark - 中心接受外設信息,外設通知手機連接成功的時候并不會調(diào)用這個函數(shù);手機向外設發(fā)送消息后,外設回應數(shù)據(jù),這個函數(shù)會接受到數(shù)據(jù)。

-(void)peripheral:(CBPeripheral*)peripheral didUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error{

;

?? ? Byte* resultByte1 = (Byte*)[characteristic.valuebytes];


? ? if(resultByte1 ==NULL){

? ? ? ? return;

? ? }


? ? ? ? switch(self.commandIndex) {

? ? ? ? ? ? case1:

? ? ? ? ? ? {

? ? ? ? ? ? ? ? [self processingDataAWithdictionary:self.equipmentData characteristic:characteristic];

//命令1和命令2中間間隔300毫秒

? ? ? ? ? ? ? ? [self performSelector:@selector(senderB) withObject:nil afterDelay:0.3f];


? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case2:

? ? ? ? ? ? {

? ? ? ? ? ? ? ? [self processingDataBWithdictionary:self.equipmentData characteristic:characteristic];

? ? ? ? ? ? ? ? [self performSelector:@selector(senderC) withObject:nil afterDelay:0.3f];


? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case3:

? ? ? ? ? ? {

? ? ? ? ? ? ? ? [self processingDataCWithdictionary:self.equipmentData characteristic:characteristic];

? ? ? ? ? ? ? ? if(self.delegate&& [self.delegaterespondsToSelector:@selector(sendCommandABCForALoop)]){

//1,2,3命令查詢后調(diào)用停止鏈接的回調(diào)

? ? ? ? ? ? ? ? ? ? [self.delegate sendCommandABCForALoop];

? ? ? ? ? ? ? ? }



? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case4:

? ? ? ? ? ? {

? ? ? ? ? ? ? ? [self processingDataDWithdictionary:self.equipmentData characteristic:characteristic];




? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case5:

? ? ? ? ? ? {

? ? ? ? ? ? ? ? [self processingDataEWithdictionary:self.equipmentData characteristic:characteristic];




? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? break;

? ? ? ? }


? ? //? ? NSLog(@"dataDic=====%@",dataDic);

? ? //? ? NSLog(@"resultByte=====%s",resultByte);

//? ? NSLog(@"resultByte1=====%s",resultByte1);

}

-(void)peripheral:(CBPeripheral*)peripheraldidWriteValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error{

? ? NSLog(@"didWriteValueForCharacteristic=====%ld",characteristic.properties);

? ? [self.connectedPeripheral readValueForCharacteristic:self.characteristicTX];

}

//向藍牙發(fā)送命令

-(void)sendMsgWithSubPackage:(NSString*)msg? {

//將命令轉(zhuǎn)成NSData格式發(fā)送

? ? NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];


? ? if(self.characteristicRX){

? ? ? ? [self.connectedPeripheral writeValue:data forCharacteristic:self.characteristicRX type:(CBCharacteristicWriteWithResponse)];

? ? }

}

-(NSArray *)peripheralArray{

? ? if(!_peripheralArray){

? ? ? ? _peripheralArray = [NSArray array];


? ? }

? ? return _peripheralArray;

}

//CRC驗證

-(uint16_t)getCrcCode:(Byte*)bytes{

//這里一定得用uint16_t 格式的,安卓用的int,之前仿安卓的用int,打印的CRC一直都是0,找了很長時間

? ? uint16_t CRC =0x0000000;

? ? uint16_t POLYNOMIAL =;


? ? for(inti =0; i<13; i++) {

? ? ? ? CRC ^= (bytes[i] <<8);

? ? ? ? for(intj =0; j <8; j++) {


//? ? ? ? ? ? NSLog(@"CRC=%d=======%x ",j,CRC);

? ? ? ? ? ? if((CRC &0x8000) !=0){

? ? ? ? ? ? ? ? CRC <<=1;

? ? ? ? ? ? ? ? CRC ^= POLYNOMIAL;


? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? CRC <<=1;

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? returnCRC &0xff;

}


//將data轉(zhuǎn)16進制

-(NSArray *)ConvertToNSString:(NSData *)data{


? ? NSMutableArray *mutArr = [NSMutableArray array];

? ? for(inti =0; i < data.length; i++) {

? ? ? ? NSData*lengthData = [data subdataWithRange:NSMakeRange(i,1)];//取得長度數(shù)據(jù)

? ? ? ? NSString* hexString = [self?convertDataToHexStr:lengthData];

? ? ? ? [mutArr addObject:hexString];

? ? }

? ? return?mutArr;

}

//將藍牙發(fā)送的數(shù)據(jù)data轉(zhuǎn)成NSString

- (NSString *)convertDataToHexStr:(NSData *)data{

? ? if(!data || [data length] ==0) {

? ? ? ? return@"";

? ? }

? ? NSMutableString*string = [[NSMutableString alloc]initWithCapacity:[data length]];

? ? [data enumerateByteRangesUsingBlock:^(constvoid*bytes,NSRangebyteRange,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;

}

@end

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容