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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章