美文网首页
iOS 通过蓝牙给设备发送命令并接收回复信息

iOS 通过蓝牙给设备发送命令并接收回复信息

作者: 神一样的队友 | 来源:发表于2023-02-09 17:24 被阅读0次

#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

相关文章

网友评论

      本文标题:iOS 通过蓝牙给设备发送命令并接收回复信息

      本文链接:https://www.haomeiwen.com/subject/rokhkdtx.html