#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
NS_ASSUME_NONNULL_BEGIN
#define kCharacteristicTXUUID @""
#define kCharacteristicRXUUID @""
#define kServicesID @""
@protocol EquipmentManagerDelegate <NSObject>
@optional
//发送命令返回的值
-(void)sendCommandABackWithdictionary:(NSDictionary *)dictionary;
-(void)sendCommandBBackWithdictionary:(NSDictionary *)dictionary;
-(void)sendCommandCBackWithdictionary:(NSDictionary *)dictionary;
-(void)sendCommandDBackWithdictionary:(NSDictionary *)dictionary byte2:(Byte)byte2;
-(void)sendCommandEBackWithdictionary:(NSDictionary *)dictionary;
//发送abc命令 一个循环
-(void)sendCommandABCForALoop;
//手机的的蓝牙状态
-(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 数组
@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 接收发送命令的值
NSData*dataValue= characteristic.value;
if(dataValue.length!=17){
return;
}
//将返回的data拆分成对应的字符串字节数组
NSArray*dataArr = [self ConvertToNSString:dataValue];
//将dataArr里的字符串转成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;
}
//处理蓝牙发过来的数据处理
NSMutableDictionary *data = [NSMutableDictionary dictionaryWithDictionary:oldDictionary];
self.equipmentData= data;
if(self.delegate&& [self.delegaterespondsToSelector:@selector(sendCommandABackWithdictionary:)]){
[self.delegate sendCommandABackWithdictionary:data];
}
}
//VC调用命令后发送给蓝牙
-(void)setCommandStr:(NSString*)commandStr{
_commandStr= commandStr;
[self sendMsgWithSubPackage:_commandStr];
}
//清除警告 向蓝牙设备发送命令
-(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.实现已连接外设的回调 查找服务
-(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.发现服务就会调用代理方法
*
* @param peripheral 外设
*/
-(void)peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error{
// 扫描到设备的所有服务
NSArray*services = peripheral.services;
// 根据服务再次扫描每个服务对应的特征
for(CBService*sesinservices) {
if([ses.UUID.UUIDString isEqualToString:kServicesID]){
[peripheraldiscoverCharacteristics:nil forService:ses];
}
}
}
/**
* 4.发现服务对应的特征
*/
-(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];
// 根据特征的唯一标示过滤
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 - 中心接受外设信息,外设通知手机连接成功的时候并不会调用这个函数;手机向外设发送消息后,外设回应数据,这个函数会接受到数据。
-(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命令查询后调用停止链接的回调
[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];
}
//向蓝牙发送命令
-(void)sendMsgWithSubPackage:(NSString*)msg {
//将命令转成NSData格式发送
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转16进制
-(NSArray *)ConvertToNSString:(NSData *)data{
NSMutableArray *mutArr = [NSMutableArray array];
for(inti =0; i < data.length; i++) {
NSData*lengthData = [data subdataWithRange:NSMakeRange(i,1)];//取得长度数据
NSString* hexString = [self convertDataToHexStr:lengthData];
[mutArr addObject:hexString];
}
return mutArr;
}
//将蓝牙发送的数据data转成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