ios ble 蓝牙锁开发用例

开发流程:

1. 建立中心管家
2. 扫描外部设备
3. 获取扫描的 外部设备,获取外部设备 , 连接外部设备
 4.  连接外设 成功,获取  发现服务
 5.  发现服务 uuid, 发现 服务下 特征值
 6.  读取 特征值  ,订阅 ble->app 通道   获取app->ble 特征值
 7.  接收 读取的特征值
 8. 锁入网,传递psw2 给app
 9. p1+p2 加密 systemId 鉴权
  10. 锁回复 psw3
  11.发送  开锁 确认帧 

 代码实现: 

//
//  ViewController.m
//  mutipeerConnectivityTest
//
//  Created by 邓安置 on 2020/6/11.
//  Copyright © 2020 邓安置. All rights reserved.
//

#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import "CBPeripheral+Extension.h"
#import "KDSBleOptions.h"
#import "NSData+JKEncrypt.h"
#import "KDSBleAssistant.h"
#import "NSTimer+KDSBlock.h"
@interface ViewController ()<CBCentralManagerDelegate,CBPeripheralDelegate>

@property(nonatomic,strong) CBCentralManager* mgr;


@property(nonatomic,strong) CBPeripheral*  peripheral;


@property(nonatomic,copy,nullable) void(^myBlock)(CBPeripheral* cbP);


@property (nonatomic, strong) CBCharacteristic *batteryCharacteristic; //电量
@property (nonatomic, strong) CBCharacteristic *systemIDCharacteristic; //系统ID
@property (nonatomic, strong) CBCharacteristic *modelNumCharacteristic; //
@property (nonatomic, strong) CBCharacteristic *seriaNumCharacteristic; //
///要写入到哪个特征
@property (nonatomic, strong) CBCharacteristic *writeCharacteristic;
@property (nonatomic, strong) CBCharacteristic *functionSetCharacteristic;//功能集
@property (nonatomic, strong, nullable) CBPeripheral *connectedPeripheral;

@property (nonatomic, strong) NSData *systemID;

///连接外设绑定时,收到SN后,从服务器请求回来。绑定后从绑定设备列表获得。测试没有上市的蓝牙时,服务器没有值返回,这是使用mac提取。
@property (nonatomic, copy, nullable) NSString  *pwd1;
///用户入网(绑定)的时候生成,锁蓝牙返回的payload数据的1~4字节。
@property (nonatomic, strong, nullable) NSData *pwd2;
///鉴权成功时,锁蓝牙返回的payload数据的1~4字节。
@property (nonatomic, strong, nullable) NSData *pwd3;

/**传输序号,每次传输+1,到了255置为50 (为了区分心跳包 设置范围为50-255)*/
@property (nonatomic, assign) int tsn;


///心跳包tsn 1 - 49
@property (nonatomic, assign) NSInteger heartbeatTsn;
@property (nonatomic, weak) NSTimer *heartbeatTimer;
@end

@implementation ViewController



- (IBAction)searchShow:(id)sender {
    
    // 1. 建立中心管家
    // nil: 在主线程中扫描
        CBCentralManager *centralManager= [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        _mgr = centralManager;
        NSLog(@"%@",@"开始扫描");
     //
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.myBlock= ^(CBPeripheral* cbP){
        NSLog(@"block回调--->%@",cbP.advDataLocalName);
    };
    
     self.pwd1=@"62375ea279e77356aa0a77f9";
    
}

-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
     NSLog(@"%ld",central.state);
    // 开机状态   5
    if(central.state== CBManagerStatePoweredOn ){
       // 2. 扫描外部设备      CBPeripheral表示外部设备
        [self.mgr scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
    }
    
     __weak typeof(self) weakSelf = self;
    dispatch_block_t block = dispatch_block_create(DISPATCH_BLOCK_ASSIGN_CURRENT, ^{
        if (weakSelf.mgr.isScanning) {
            [weakSelf stopScan];
        }
    });
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
           block();
       });
    
}

- (void)stopScan
{
    NSLog(@"%@",@"停止扫描");
    [self.mgr stopScan];
}

-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    /**
       ===peripheral名:Kaadas DoorLock
       ===广播名:KDSF0F8F2BFB618
       ===设备uuid:22F116CE-D746-16A4-8408-BE1476E11B0C
       ===peripheral:<CBPeripheral: 0x2822b4fa0, identifier = 22F116CE-D746-16A4-8408-BE1476E11B0C, name = Kaadas DoorLock, state = disconnected>
       ===设备广播数据:{
         kCBAdvDataIsConnectable = 1;
         kCBAdvDataLocalName = KDSF0F8F2BFB618;
         kCBAdvDataRxPrimaryPHY = 0;
         kCBAdvDataRxSecondaryPHY = 0;
         kCBAdvDataServiceUUIDs =     (
             FFD0,
             FFF0
         );
         kCBAdvDataTimestamp = "614075187.3347189";
         kCBAdvDataTxPowerLevel = 0;
     }
     */
//    NSLog(@"\n\n===peripheral名:%@ \n===广播名:%@\n ===设备uuid:%@\n  ===peripheral:%@\n ===设备广播数据:%@\n\n",peripheral.name,advertisementData[@"kCBAdvDataLocalName"],peripheral.identifier.UUIDString,peripheral,advertisementData);
    //解析广播包中的kCBAdvDataLocalName 区分凯迪仕的设备
     NSString *key = CBAdvertisementDataLocalNameKey;
    // 3. 获取扫描的 外部设备,获取外部设备 , 连接外部设备
    if (peripheral==nil || peripheral.name==nil || ![advertisementData[key] containsString:@"KDSA434F1CC143A"]) return;
    [self stopScan];
    NSLog(@"peripheral==%@",advertisementData[key]);
    peripheral.advDataLocalName = advertisementData[key];
    self.myBlock(peripheral);
    self.peripheral = peripheral;
    // 连接外部设备
    [self.mgr connectPeripheral:peripheral options:nil];
}

// 4.  连接外设 成功,获取  发现服务
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    // 通过连接的外部设置保存扫描到的
    NSLog(@"连接成功:%@",peripheral.advDataLocalName);
     _connectedPeripheral = peripheral;
    NSInteger allLenth =peripheral.advDataLocalName.length;
     if (allLenth >= 12) {
          NSString *orgStr = [peripheral.advDataLocalName substringFromIndex:allLenth-12];
          NSData *password1 = [orgStr dataUsingEncoding:NSASCIIStringEncoding];
         
     }

    peripheral.delegate =self;
    //  扫描服务 根据服务 扫描特征值
    [self.peripheral discoverServices:nil];
}
// 5.  发现服务 uuid, 发现 服务下 特征值
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    NSArray* services= peripheral.services;
    NSLog(@"设备服务值:%@",services);
    for (CBService *sevice in peripheral.services) {
        /**
         设备服务值:(
             "<CBService: 0x2803c6800, isPrimary = YES, UUID = Device Information>",
             "<CBService: 0x2803c5840, isPrimary = YES, UUID = FFF0>",
             "<CBService: 0x2803c66c0, isPrimary = YES, UUID = FFE0>",
             "<CBService: 0x2803c6740, isPrimary = YES, UUID = FFE5>",
             "<CBService: 0x2803c6640, isPrimary = YES, UUID = FFB0>",
             "<CBService: 0x2803c60c0, isPrimary = YES, UUID = F000FFD0-0451-4000-B000-000000000000>"
         )
         */
        
      //  NSLog(@"%@",sevice.UUID.UUIDString);
        
        if ([sevice.UUID.UUIDString isEqualToString:OADResetServiceUUID]
                     ||[sevice.UUID.UUIDString isEqualToString:DFUResetServiceUUID]) {

               //存在FFD0或1802服务,OAD复位服务
            //存在FFD0或1802服务,OAD复位服务
            peripheral.isNewDevice = YES;
            peripheral.bleVersion = 2;
            NSLog(@"--{Kaadas}--bleVersion:%d",peripheral.bleVersion);
        }
        [peripheral discoverCharacteristics:nil forService:sevice];//发现服务下面所有的特征
    }
}
// 6.  读取 特征值  ,订阅 ble->app 通道   获取app->ble 特征值,发送 心跳包
// 发现特征值就会调用
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {
    
    if (error){
         NSLog(@"获取服务:%@的特征失败: %@", service.UUID, error);
         return;
     }
   
    
    UInt64 uuid = strtoul(service.UUID.UUIDString.UTF8String, 0, 16);
    KDSBleService serviceType = (KDSBleService)uuid;
    NSLog(@"读的服务-service===%@",service.characteristics);
    switch (serviceType)
       {
           case KDSBleServiceModule:
               for (CBCharacteristic *characteristic in service.characteristics) {
                   NSLog(@"读的服务-模块信息 (电量 pwd3):severUUId:%@====charUUId:%@",service.UUID.UUIDString,characteristic.UUID.UUIDString);
                  // [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                   if ([characteristic.UUID.UUIDString isEqualToString:batteryDUUID]) {
                       [peripheral readValueForCharacteristic:characteristic];
                       //电量特征值
                       _batteryCharacteristic = characteristic;
                   }
               }
               break;
           case KDSBleServiceDevice:
             for (CBCharacteristic *characteristic in service.characteristics) {
                   NSLog(@"读的服务-BLE设备信息参数:severUUId:%@====charUUId:%@",service.UUID.UUIDString,characteristic.UUID.UUIDString);
                   //监听characteristic值变化
                //   [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                   if ([characteristic.UUID.UUIDString isEqualToString:systemIDUUID]) {
                       _systemIDCharacteristic = characteristic;
                       [peripheral readValueForCharacteristic:characteristic];
                   }
                   else if ([characteristic.UUID.UUIDString isEqualToString:modelNumUUID]) {
                       _modelNumCharacteristic = characteristic;
                       [peripheral readValueForCharacteristic:characteristic];
                   }
                   else if ([characteristic.UUID.UUIDString isEqualToString:seriaLNumUUID]) {
                       _seriaNumCharacteristic = characteristic;
                       [peripheral readValueForCharacteristic:characteristic];
                   }
               }
               break;
           case KDSBleServiceLock:
               
               break;
           case KDSBleServiceApp2BleTunnel:  // app->蓝牙  0xFFE5 ,下只有一个特征值,app->ble
                for (CBCharacteristic *characteristic in service.characteristics) {
                    NSLog(@"读的服务-APP-->BLE数据通道severUUId:%@====charUUId:%@",service.UUID.UUIDString,characteristic.UUID.UUIDString);
                                       //主动去读取一次外围设备的消息
                   [peripheral readValueForCharacteristic:characteristic];
                 //  [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                   self.writeCharacteristic = characteristic;
                }
               if(self.connectedPeripheral.isNewDevice){
                    [self createHeartbeatTimer];
               }
                
               break;
           case KDSBleServiceBle2AppTunnel:    //0xFFE0
               for (CBCharacteristic *characteristic in service.characteristics) {
                              NSLog(@"读的服务-BLE-->APP数据通道:severUUId:%@====charUUId:%@",service.UUID.UUIDString,characteristic.UUID.UUIDString);
                              [peripheral setNotifyValue:YES forCharacteristic:characteristic];
                   // ffe0 下功能集 ffe1
                              if ([characteristic.UUID.UUIDString isEqualToString:kFFE1])
                              {
                                  peripheral.bleVersion = 3;
                                  NSLog(@"--{Kaadas}--bleVersion:%d",peripheral.bleVersion);
                                  _functionSetCharacteristic = characteristic;
                                  [peripheral readValueForCharacteristic:characteristic];
                              }
                          }
               break;
           case KDSApp2BleDisNetworkTunnel:
               
               break;
           case KDSBle2AppDisNetworkTunnel:
               
               break;
       }
}

// 7.  接收 读取的特征值 ,
#pragma mark 接收特征的数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    if (error) return;
    
      NSString *uuid = characteristic.UUID.UUIDString;
      NSLog(@"读取所有特征值的时候蓝牙UUID的值:%@",uuid);
    
    
    if ([uuid isEqualToString:batteryDUUID]) {//电量信息
        NSData *batteryData = characteristic.value;
        u_int8_t tt;
        [batteryData getBytes:&tt length:sizeof(tt)];
        int elct = tt;//0-100
        peripheral.power = elct;
        NSLog(@"电量值是=%d",elct);
    }
    
    else if ([uuid isEqualToString:seriaLNumUUID]) {//SN
         peripheral.serialNumber = characteristic.value.jk_UTF8String;
        NSLog(@"sn是=%@",peripheral.serialNumber);
     }

    else if ([uuid isEqualToString:systemIDUUID]){//System ID
            //获取systemId
                   _systemID = characteristic.value;
                   NSString *systemIDStr = [KDSBleAssistant convertDataToHexStr:_systemID];
                   if (!systemIDStr || strtol(systemIDStr.UTF8String, NULL, 16) == 0) {
                       _systemID = [KDSBleAssistant extractSystemIDFromAdvName:peripheral.advDataLocalName];
                   }
           NSLog(@"systemID是=%@",_systemID);
    }
    
    else if ([uuid isEqualToString:modelNumUUID])  //  modulenum
       {
           self.connectedPeripheral.lockModelNumber = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
           
           NSLog(@"modulenum是=%@",self.connectedPeripheral.lockModelNumber);
       }
    else if ([uuid isEqualToString:bleToAppDUUID]){//模块向App发送数据通道
          if (characteristic.value.length == 16) {  //没用,都是20个字节
              NSData *pwd1Data = [characteristic.value subdataWithRange:NSMakeRange(0, 12)];
              NSData *pwd = [KDSBleAssistant convertHexStrToData:self.pwd1];
              NSString* pwdS= [KDSBleAssistant convertDataToHexStr:pwd];
              NSLog(@"%@",pwdS);
              return;
          }
          if (characteristic.value.length < 20) {return;/**数据丢包了 */ }
            //新设备数据的处理
                      NSData *data = characteristic.value;
                      NSLog(@"--{Kaadas}--蓝牙--处理模块发来的数据==%@",data);
                      const unsigned char* bytes = (const unsigned char*)data.bytes;
                      u_int8_t control = bytes[0];
                      u_int8_t check1 = bytes[2];
                      NSData *decryptData = data;
                      if (control != 0) {//心跳包不加密
                         //解密数据
                          decryptData =  [self getAes256_decryptDataWithOriginData:data];
                          NSLog(@"解密以后的数据:%@",[KDSBleAssistant convertDataToHexStr:decryptData]);
                      }
                      u_int8_t check2 = [KDSBleAssistant sumOfDataThroughoutBytes:[decryptData subdataWithRange:NSMakeRange(4, 16)]];
                      if (check1 == check2) {
                     //      KDSLog(@"校验正确=%@",decryptData)
                           NSLog(@"处理校验正确之后的数据------%@",decryptData);
                           const unsigned char *bytes = (const unsigned char *)decryptData.bytes;
                           unsigned char transferSerialNumber = bytes[1];  //tsn
                           unsigned char cmd = bytes[3];
                           unsigned char status = bytes[4];
                           if (cmd==0 && transferSerialNumber<50) return;//心跳包确认帧。
                           NSString *receipt = @(transferSerialNumber).stringValue;
                           //如果是app主动发送命令,那么队列里会有记录,根据tsn和命令值执行相应的命令就行。
                           //执行app主动发送命令队列中不存在的上报命令
                           KDSBleTunnelOrder order = (KDSBleTunnelOrder)cmd;
                           switch (order) {
                                 case KDSBleTunnelOrderEncrypt:
                                   // 8. 锁入网,传递psw2 给app
                                     if (status == 1)//收到锁发送过来的入网(绑定)指令,可以在返回数据中提取pwd2
                                      {
                                         self.pwd2 = [decryptData subdataWithRange:NSMakeRange(5, 4)];
                                          // 9. p1+p2 加密 systemId 鉴权
                                         [self sendResponseInOrOutNet:(int)transferSerialNumber];
                                         NSLog(@"~~~~~收到入网命令self.pwd2=%@",self.pwd2);
                                         [self authenticationWithPwd1:self.pwd1 pwd2:self.pwd2];
                                     }
                                    else if (status == 2)//收到pwd3,绑定成功。
                                    {
                                        // 10. 锁回复 psw3
                                        self.pwd3 = [decryptData subdataWithRange:NSMakeRange(5, 4)];
                                        NSLog(@"~~~~~收到self.pwd3,绑定成功=%@",self.pwd3);
                                        [self sendResponseInOrOutNet:(int)transferSerialNumber];
                                    }
                                      break;
                               case KDSBleTunnelOrderLockOperate:
                                   NSLog(@"%@",@"锁操作上报");
                                   
                                   break;
                           };
                          
                      }else{
                          NSLog(@"--{Kaadas}--校验出错--check1=%d--check2=%d",check1,check2);
                     }
  
         
    }
    
    else if ([uuid isEqualToString:kFFE1])//功能集
     {
      
        NSString *FunctionSetKey = [NSString stringWithFormat:@"0x%@",[KDSBleAssistant convertDataToHexStr:characteristic.value]];
    
        NSLog(@"--{Kaadas}--功能集=锁上=%@",FunctionSetKey);
     
     }
}


#pragma mark - 获取解密数据
///解密数据,绑定/重置时只能使用密码1+4字节都为0的NSData解密(即密码2必须为nil);鉴权时只能使用密码1+密码2解密(即密码3必须为nil);鉴权成功获取密码3后只能使用密码1+密码3解密;否则解密的数据都不正确。
- (NSData *)getAes256_decryptDataWithOriginData:(NSData *)data{
    NSMutableData *keyData = [NSMutableData data];
    NSData *key1Data = [KDSBleAssistant convertHexStrToData:_pwd1]; //12个字节
    [keyData appendData:key1Data];
    if (self.pwd2 == nil) {//解密pwd2  4个字节
        Byte behindByte[] = {0x00,0x00,0x00,0x00};
        NSData *behindData= [NSData dataWithBytes:behindByte length:sizeof(behindByte)];
        [keyData appendData:behindData];
        NSLog(@"keyData:%@",keyData);
        
    }else if(self.pwd2 && self.pwd3 == nil){//解密pwd3
        [keyData appendData:self.pwd2];
        NSLog(@"keyData2:%@",keyData);
    }
    else if(self.pwd2 && self.pwd3){//建立通道以后 解密数据
        [keyData appendData:self.pwd3];
//        KDSLog(@"keyData3:%@",keyData);
    }
//    KDSLog(@"收到的原始数据:%@",data);
    NSData *resultData = [[data subdataWithRange:NSMakeRange(4, 16)] aes256_decryptData:keyData];
    NSMutableData *decryptData = [NSMutableData data];
    [decryptData appendData:[data subdataWithRange:NSMakeRange(0, 4)]];
    [decryptData appendData:resultData];
//    KDSLog(@"--{Kaadas}--蓝牙--收到的解密后数据%@",decryptData);
    return decryptData.copy;
}

#pragma mark - 发送收到 入网/退网 确认帧
- (void)sendResponseInOrOutNet:(int)tsn{
    if (_connectedPeripheral.isNewDevice) {
        [self sendConfirmDataToBleDevice:tsn];
        return;
    }
}
#pragma mark - 新模块发送确认帧
- (void)sendConfirmDataToBleDevice:(NSInteger)tsn{
    if (tsn != 0) {
//        [self pauseTimer];
        Byte conformByte[] = {0x00,tsn,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
        NSData *conformData = [[NSData alloc] initWithBytes:conformByte length:sizeof(conformByte)];
        if (self.writeCharacteristic && self.connectedPeripheral ) {///设备已经连接且要写入特征
//            KDSLog(@"发送了确认帧:%@ %@",conformData,getcurretenDate);
            [self.connectedPeripheral writeValue:conformData forCharacteristic:self.writeCharacteristic type:0];
        }
        return;
    }
}

- (NSString *)authenticationWithPwd1:(NSString *)pwd1 pwd2:(id)pwd2
{
      Byte payload[16] = {0};
      for (int i = 0; i < self.systemID.length; ++i)
      {
          // 把NSData 转化为 Byte
          payload[i] = ((Byte *)self.systemID.bytes)[i];
      }
      int sum = [KDSBleAssistant sumOfDataThroughoutBytes:[[NSData alloc] initWithBytes:payload length:16]];
      self.tsn++;
      unsigned char* bytes = (unsigned char*)malloc(20);
      bytes[0] = 1; bytes[1] = self.tsn; bytes[2] = sum; bytes[3] = KDSBleTunnelOrderAuth;
      memcpy(bytes + 4, payload, 16);
      NSData* sendData= [[NSData alloc] initWithBytesNoCopy:bytes length:20];
    
    
      NSMutableData *key = [NSMutableData dataWithData:[KDSBleAssistant convertHexStrToData:self.pwd1]]; //12个字节
      [key appendData:self.pwd2];  //4个字节
      NSData *encryptData = [[sendData subdataWithRange:NSMakeRange(4, 16)] aes256_encryptData:key];
      
      NSLog(@"--{Kaadas}--encryptData=key=%@",key);
      NSLog(@"--{Kaadas}--encryptData====%@",encryptData);
      [key setData:[sendData subdataWithRange:NSMakeRange(0, 4)]];
      [key appendData:encryptData];
    
      [self.connectedPeripheral writeValue:key forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];
    
    return nil;
    
}

#pragma mark - 发送心跳包
- (void)createHeartbeatTimer{
    if (self.heartbeatTimer==nil) {
        //重复每3秒发送一次心跳包
        __weak typeof(self) weakSelf = self;
        NSTimer *timer = [NSTimer kdsScheduledTimerWithTimeInterval:3 repeats:YES block:^(NSTimer * _Nonnull timer) {
             self.heartbeatTsn ++;
             Byte bytePayload[16] = {0xFF, 0};
             NSData *payloadData = [[NSData alloc] initWithBytes:bytePayload length:sizeof(bytePayload)];
             Byte byteHeader[] = {0x00,self.heartbeatTsn,0xff,0xAA};
             NSData *headerData = [[NSData alloc] initWithBytes:byteHeader length:sizeof(byteHeader)];
             NSMutableData *senderData = [NSMutableData data];
             [senderData appendData:headerData];
             [senderData appendData:payloadData];
             NSLog(@"发送心跳:%@",[KDSBleAssistant convertDataToHexStr:senderData]);
             [self.connectedPeripheral writeValue:senderData forCharacteristic:self.writeCharacteristic type:0];
            
        }];
        self.heartbeatTimer = timer;
        [timer fire];
    }
}
// 如果发送开锁命令,暂停3s发送心跳包
- (void)pauseTimer{
    self.heartbeatTimer.fireDate = [NSDate dateWithTimeIntervalSinceNow:3];
}

- (IBAction)openLock:(id)sender {
    
    [self operateLockWithPwd:@"147258" actionType:KDSBleLockControlActionUnlock keyType:KDSBleLockControlKeyPIN
                  completion:^(KDSBleError error, CBPeripheral * _Nullable peripheral) {
        
    }];
        
}
// 11.发送  开锁 确认帧
- (NSString *)operateLockWithPwd:(NSString *)pwd actionType:(KDSBleLockControl)action keyType:(KDSBleLockControl)key completion:(nullable void(^)(KDSBleError error, CBPeripheral * __nullable peripheral))completion{
   
    Byte payload[16] = {(char)action, (char)key, 0, 0};
    
    payload[3] = pwd.length;//密码长度
    //第4个字节开始是密码,每一个字节保存一位密码。
    for (int i = 0; i< pwd.length; i++)
    {
        payload[i + 4] = pwd.UTF8String[i];
    }
    int sum = [KDSBleAssistant sumOfDataThroughoutBytes:[[NSData alloc] initWithBytes:payload length:16]];
    self.tsn++;
    unsigned char* bytes = (unsigned char*)malloc(20);
    bytes[0] = 1; bytes[1] = self.tsn; bytes[2] = sum; bytes[3] = KDSBleTunnelOrderControl;
    memcpy(bytes + 4, payload, 16);
    
    NSData* sendData= [[NSData alloc] initWithBytesNoCopy:bytes length:20];
    
    
    NSMutableData *key13 = [NSMutableData dataWithData:[KDSBleAssistant convertHexStrToData:self.pwd1]];
    if (self.pwd3)//鉴权后+密码3加密
    {
        [key13 appendData:self.pwd3];
    }
    NSData *encryptData = [[sendData subdataWithRange:NSMakeRange(4, 16)] aes256_encryptData:key13];
    [key13 setData:[sendData subdataWithRange:NSMakeRange(0, 4)]];
    [key13 appendData:encryptData];
    
    [self.connectedPeripheral writeValue:key13 forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];
    
    return nil;
}


@end

源码下载 : https://download.csdn.net/download/dreams_deng/12576424

猜你喜欢

转载自blog.csdn.net/dreams_deng/article/details/107126490