美文网首页
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