iOS 蓝牙开发

作者: 奋斗的小马达 | 来源:发表于2021-03-24 17:20 被阅读0次

    前言:此篇文章只针对第一次接触蓝牙的小白,文章中仅仅描述了如何连接蓝牙、如何发送数据 、可能遇到的问题 等。对于其他专业性的名词没有做相应的描述。

    一、准备工作
    1、iOS使用蓝牙 必须先允许定位,所以需要开启定位。使用蓝牙需要用户同意才可使用 所以 工程info.plist 文件中需要添加 定位请求和蓝牙请求的权限

    定位权限
    Privacy - Location When In Use Usage Description 
    
    蓝牙权限
    Privacy - Bluetooth Peripheral Usage Description
    

    2、使用蓝牙首先要准备几个UUID

    服务UUID
    #define BLE_SERVICE_UUID   @"0000XXXX-0000-1000-8000-00805f9b34fb"
    
    读UUID
    #define BLE_INDICATE_CHARACTERISTIC_UUID   @"0000XXXX-0000-1000-8000-00805f9b34fb"
    
    写UUID
    #define BLE_WRITE_CHARACTERISTIC_UUID   @"0000XXXX-0000-1000-8000-00805f9b34fb"
    
    

    这几个UUID开发硬件的工程师会直接给你。作用后面会有所体验

    二、设置相关代码

    1、首先引入蓝牙和定位所需框架

    #import <SystemConfiguration/CaptiveNetwork.h>
    #import <CoreLocation/CoreLocation.h>
    #import <CoreBluetooth/CoreBluetooth.h>
    

    2、其次引入代理

    CBCentralManagerDelegate
    CBPeripheralDelegate
    
    

    3、然后声明属性

    @property (nonatomic, strong) CBCentralManager  * bluetoothManager;
    @property (nonatomic, strong) CLLocationManager * locationManager;
    @property (nonatomic, strong) CBPeripheral      * currentPer;
    

    4、设置定位

    - (void)location {
        NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];
        CGFloat version = [phoneVersion floatValue];
        // 如果是iOS13 未开启地理位置权限 需要提示一下
        if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined && version >= 13) {
          self.locationManager = [[CLLocationManager alloc] init];
          [self.locationManager requestWhenInUseAuthorization];
        }
    }
    

    重点来了,以下代码是蓝牙相关的代码

    1、初始化 CBCentralManager

    #pragma mark--  CBCentralManager的实例对象
    - (void)initCBCentralManager{
        NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey: @YES};
        CBCentralManager* cBCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
        self.bluetoothManager = cBCentralManager;
    }
    

    2、 CBCentralManagerDelegate回调:返回蓝牙的状态 在此函数中可以提醒用户打开蓝牙等操作

    #pragma mark--  CBCentralManagerDelegate回调:(开启/关闭蓝牙,也就是蓝牙的状态)
    - (void)centralManagerDidUpdateState:(CBCentralManager*)central{
        if (central.state == CBCentralManagerStatePoweredOn) {
            NSLog(@"蓝牙已经打开");
        } else if (central.state == CBManagerStatePoweredOff) {
            NSLog(@"蓝牙已经关闭");
        }
    }
    

    3、开始扫描蓝牙设备

    #pragma  mark-- 开始扫描设备(也就是开始扫描蓝牙)
    - (void)scanDevice{
        [self.bluetoothManager scanForPeripheralsWithServices:nil options:nil];
    }
    

    4、蓝牙设备扫描结果回调:在此方法中找到你想要连接的蓝牙设备然后去连接设备

    #pragma mark--  CBCentralManagerDelegate回调:蓝牙搜索结果回调
    - (void)centralManager:(CBCentralManager*)central didDiscoverPeripheral:(CBPeripheral*)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber*)RSSI{
        NSString *scanedName=advertisementData[@"kCBAdvDataLocalName"];
        if (scanedName.length>0) {
            NSLog(@"扫描到设备scanedName=:%@",scanedName);
        }
        if ([scanedName hasPrefix:@"aux-5802"]) {
            self.currentPer = peripheral;
            // 发现设备后,请求连接设备
            [self connectedDevices];
        }
    }
    
    
    #pragma mark-- 开始连接设备:
    - (void)connectedDevices{
        [self.bluetoothManager connectPeripheral:self.currentPer options:nil];
    }
    

    5、连接状态回调

    #pragma mark-- 链接状态回调
    ///连接成功
    - (void)centralManager:(CBCentralManager*)central didConnectPeripheral:(CBPeripheral*)peripheral{
        NSLog(@"连接成功");
        //连接成功停止搜索
        [self.bluetoothManager stopScan];
    
        self.currentPer = peripheral;
    
    //连接成功后,扫描外围设备的服务CBService:
      [self scanDeviceCBService];
        
    }
    
    ///连接失败
    - (void)centralManager:(CBCentralManager*)central didFailToConnectPeripheral:(CBPeripheral*)peripheral error:(NSError*)error{
        NSLog(@"连接失败---%@",error);
    }
    
    ///断开连接结果
    - (void)centralManager:(CBCentralManager*)central didDisconnectPeripheral:(CBPeripheral*)peripheral error:(NSError*)error{
        NSLog(@"断开链接");
    }
    
    
    #pragma mark-- 连接成功后,扫描外围设备的服务CBService:
    - (void)scanDeviceCBService{
        self.currentPer.delegate = self;
        [ self.currentPer discoverServices:@[[CBUUID UUIDWithString:BLE_SERVICE_UUID]]];
    }
    

    6、 扫描服务结果会通过CBPeripheralDelegate回调 返回

    #pragma mark-- 扫描服务结果会通过CBPeripheralDelegate回调:
    - (void)peripheral:(CBPeripheral*)peripheral didDiscoverServices:(NSError*)error{
        for (CBService *service in peripheral.services) {
            if ([service.UUID isEqual:[CBUUID UUIDWithString:BLE_SERVICE_UUID]]) {
                //查找特征
                [self.currentPer discoverCharacteristics:nil forService:service];
            }
        }
    }
    

    7、查询特征结果会通过CBPeripheralDelegate回调:返回

    #pragma mark--查询特征结果会通过CBPeripheralDelegate回调:
    -(void)peripheral:(CBPeripheral*)peripheral didDiscoverCharacteristicsForService:(CBService*)service error:(NSError*)error{
        for (CBCharacteristic *character in service.characteristics) {
            NSLog(@"%@",character);
          
            if ([character.UUID isEqual:[CBUUID UUIDWithString:BLE_WRITE_CHARACTERISTIC_UUID]]) { 
      // 写
    
    //注意:1、这里的 writeValue: 传的是一个NSData类型的数据 这个数据硬件需要什么 你传什么就可以了。
    
    //注意:2、这里的 type :你需要查看硬件给你返回的什么类型然后你填什么类型就可以了,这个类型可以打印 character 查看他的 properties属性  如果硬件返回的是 0x04(CBCharacteristicPropertyWriteWithoutResponse) 那你就需要填写对应的(CBCharacteristicWriteWithoutResponse)即可,切记这一点 否则会报 读或写没有权限的 问题
                [self.currentPer writeValue:   data forCharacteristic:character type:CBCharacteristicWriteWithoutResponse];
            }else if ([character.UUID isEqual:[CBUUID UUIDWithString:BLE_INDICATE_CHARACTERISTIC_UUID]]) {
      // 读
                [self.currentPer setNotifyValue:YES forCharacteristic:character];
            }
        }   
    }
    

    8、特征的数据也是通过CBPeripheralDelegate回调

    #pragma mark-- 特征的数据也是通过CBPeripheralDelegate回调:
    - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
        NSLog(@"peripheral:%@ \n\n characteristic:%@ \n\n error:%@",peripheral, characteristic, error);
        [peripheral readValueForCharacteristic:characteristic];
    }
    

    9、蓝牙返回数据 代理方法 :这里可能会出现 Reading is not permitted 或则 Writing is not permitted 出现这个 问题不要着急 首先检查 硬件给你的 读写UUID是否正确 如果正确 再次检查 第七步 ( [self.currentPer writeValue: data forCharacteristic:character type:CBCharacteristicWriteWithoutResponse]; )中的 type是否与硬件返回的一致 确保这两点基本没有什么问题了

    - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
        if (error) {
            NSLog(@"%@",error);
        } else {
            NSData *responseData = characteristic.value;
            NSLog(@"%@",responseData);
    
    //注意:蓝牙返回的也是 NSData类型的数据 拿到数据解析数据就就可以了
            [self auxCmdParse:responseData];//这一步是解析数据
        }
    }
    

    补充:
    向蓝牙发送数据包(数据包的格式跟硬件协商好)

    - (NSData*)getData{
        NSString *ssid = self.ssid;
        NSString *key= self.password;
        NSString *paas_address= self.paas_address;
        NSString *m2m_address= self.m2m_address;
        NSString *apCode= self.apCode;;
        NSMutableData *allMData = [[NSMutableData alloc] init];
        NSData *ssidData = [ssid dataUsingEncoding: NSUTF8StringEncoding];
        NSData *keyData = [key dataUsingEncoding: NSUTF8StringEncoding];
        NSData *paas_addressData = [paas_address dataUsingEncoding:NSUTF8StringEncoding];
        NSData *m2m_addressData = [m2m_address dataUsingEncoding:NSUTF8StringEncoding];
        NSData *apcodeData = [apCode dataUsingEncoding:NSUTF8StringEncoding];
        unsigned long length = 8+(ssidData.length)+(keyData.length)+(apcodeData.length)+(m2m_addressData.length)+(paas_addressData.length)+7;
        
        Byte bhead[]= {0xa5, 0xa5, length & 0xFF, 0x00, 0x01, 0x00, 0x00,0x00};
        
        [allMData appendBytes:bhead length:8];
        Byte blen[]= {ssidData.length & 0xFF};
        [allMData appendBytes:blen length:1];
        if (blen[0]>0){
            [allMData appendBytes:[ssidData bytes] length:blen[0]];
        }
        //    //
        blen[0]= keyData.length & 0xFF;
        [allMData appendBytes:blen length:1];
        if (blen[0]>0){
            [allMData appendBytes:[keyData bytes] length:blen[0]];
        }
        
        
        blen[0]= apcodeData.length & 0xFF;
        [allMData appendBytes:blen length:1];
        if (blen[0]>0){
            [allMData appendBytes:[apcodeData bytes] length:blen[0]];
        }
        
        //    //
        blen[0]= paas_addressData.length & 0xFF;
        [allMData appendBytes:blen length:1];
        if (blen[0]>0){
            [allMData appendBytes:[paas_addressData bytes] length:blen[0]];
        }
        //
        //
        blen[0]= m2m_addressData.length & 0xFF;
        [allMData appendBytes:blen length:1];
        if (blen[0]>0){
            [allMData appendBytes:[m2m_addressData bytes] length:blen[0]];
        }
        
        
        
        int crc= [CRC crc16CCIT:allMData andLen:(int)allMData.length];
        Byte bcrc[]= {(crc>>8)&0x0ff, crc&0x0ff};
        [allMData appendBytes:bcrc length:2];
        
        return allMData;
    }
    

    接收蓝牙发来的数据包(按照规定的顺序解包)

    - (Boolean)cmdParse:(NSData *)data{
        Byte *b= (Byte *)[data bytes];
        if (b[0]== 0xa5 && b[1]== 0xa5
            && b[4]== 0x01 && b[5]== 0x10
            && b[6]== 0x00 && b[7]== 0x00
            && b[8]== 0x00 && b[9]== 0x00){
            int crcCal= [CRC crc16CCIT:data andLen:(int)data.length-2];
            int crcRcv= ((b[data.length-2] & 0x0ff) << 8) | (b[data.length-1] & 0x0ff);
            if (crcCal == crcRcv){
                _auxRplMac= [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X", b[11], b[12], b[13], b[14], b[15], b[16]];
                _auxRplPasscode= [self toHexString:b start:18 Len:b[17]];
                NSLog(@"%@",_auxRplMac);
                NSLog(@"%@",_auxRplPasscode);
                return true;
            }
        }
        return false;
    }
    
    - (NSString *)toHexString:(Byte *)b start:(int)start Len:(int)len{
        NSString *str= @"";
        for (int i=0; i<len; i++){
            str= [NSString stringWithFormat:@"%@%02X", str, b[start+i]];
        }
        return str;
    }
    

    相关文章

      网友评论

        本文标题:iOS 蓝牙开发

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