美文网首页
iOS蓝牙连接使用特征值通讯

iOS蓝牙连接使用特征值通讯

作者: 假装门口当前台 | 来源:发表于2020-03-30 17:39 被阅读0次

蓝牙通讯,今天我们将低功耗的BLE通讯,也就是使用特征值的通讯,该通讯的特点是低功耗,但是其实经常不小心就没电了。
主要方法如下

// 初始化CBCentralManagerDelegate
 mCentralManager = CBCentralManager(delegate: self, queue: .main)

//扫描搜索蓝牙
 mCentralManager?.scanForPeripherals(withServices: nil, options: nil)

// 停止扫描
 mCentralManager?.stopScan()

当调用scan搜索蓝牙的时候,如果发现到设备,sdk会回调如下函数

   func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {

    }
  // 这个是持续回调,并且会有重复蓝牙回调,所以在这里可以获取到蓝牙名字,但是却获取不到蓝牙的mac地址,需要进一步连接获取,正常情况下,这里需要做一个去重处理,避免重复连接,ios的蓝牙连接可以同时连接多个设备    

连接设备,由上面方面或者到CBPeripheral中的设备,可以对这个设备进行连接,

self.mCentralManager?.connect(peripheral, options: nil)

紧接着就等CBCentralManagerDelegate的回调

public protocol CBCentralManagerDelegate : NSObjectProtocol {

    
    /**
     *  @method centralManagerDidUpdateState:
     *
     *  @param central  The central manager whose state has changed.
     *
     *  @discussion     Invoked whenever the central manager's state has been updated. Commands should only be issued when the state is
     *                  <code>CBCentralManagerStatePoweredOn</code>. A state below <code>CBCentralManagerStatePoweredOn</code>
     *                  implies that scanning has stopped and any connected peripherals have been disconnected. If the state moves below
     *                  <code>CBCentralManagerStatePoweredOff</code>, all <code>CBPeripheral</code> objects obtained from this central
     *                  manager become invalid and must be retrieved or discovered again.
     *
     *  @see            state
     *
     */
    @available(iOS 5.0, *)
    func centralManagerDidUpdateState(_ central: CBCentralManager)

    
    /**
     *  @method centralManager:willRestoreState:
     *
     *  @param central      The central manager providing this information.
     *  @param dict         A dictionary containing information about <i>central</i> that was preserved by the system at the time the app was terminated.
     *
     *  @discussion         For apps that opt-in to state preservation and restoration, this is the first method invoked when your app is relaunched into
     *                      the background to complete some Bluetooth-related task. Use this method to synchronize your app's state with the state of the
     *                      Bluetooth system.
     *
     *  @seealso            CBCentralManagerRestoredStatePeripheralsKey;
     *  @seealso            CBCentralManagerRestoredStateScanServicesKey;
     *  @seealso            CBCentralManagerRestoredStateScanOptionsKey;
     *
     */
    @available(iOS 5.0, *)
    optional func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any])

    
    /**
     *  @method centralManager:didDiscoverPeripheral:advertisementData:RSSI:
     *
     *  @param central              The central manager providing this update.
     *  @param peripheral           A <code>CBPeripheral</code> object.
     *  @param advertisementData    A dictionary containing any advertisement and scan response data.
     *  @param RSSI                 The current RSSI of <i>peripheral</i>, in dBm. A value of <code>127</code> is reserved and indicates the RSSI
     *                              was not available.
     *
     *  @discussion                 This method is invoked while scanning, upon the discovery of <i>peripheral</i> by <i>central</i>. A discovered peripheral must
     *                              be retained in order to use it; otherwise, it is assumed to not be of interest and will be cleaned up by the central manager. For
     *                              a list of <i>advertisementData</i> keys, see {@link CBAdvertisementDataLocalNameKey} and other similar constants.
     *
     *  @seealso                    CBAdvertisementData.h
     *
     */
    @available(iOS 5.0, *)
    optional func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)

    
    /**
     *  @method centralManager:didConnectPeripheral:
     *
     *  @param central      The central manager providing this information.
     *  @param peripheral   The <code>CBPeripheral</code> that has connected.
     *
     *  @discussion         This method is invoked when a connection initiated by {@link connectPeripheral:options:} has succeeded.
     *
     */
    @available(iOS 5.0, *)
    optional func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)

    
    /**
     *  @method centralManager:didFailToConnectPeripheral:error:
     *
     *  @param central      The central manager providing this information.
     *  @param peripheral   The <code>CBPeripheral</code> that has failed to connect.
     *  @param error        The cause of the failure.
     *
     *  @discussion         This method is invoked when a connection initiated by {@link connectPeripheral:options:} has failed to complete. As connection attempts do not
     *                      timeout, the failure of a connection is atypical and usually indicative of a transient issue.
     *
     */
    @available(iOS 5.0, *)
    optional func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?)

    
    /**
     *  @method centralManager:didDisconnectPeripheral:error:
     *
     *  @param central      The central manager providing this information.
     *  @param peripheral   The <code>CBPeripheral</code> that has disconnected.
     *  @param error        If an error occurred, the cause of the failure.
     *
     *  @discussion         This method is invoked upon the disconnection of a peripheral that was connected by {@link connectPeripheral:options:}. If the disconnection
     *                      was not initiated by {@link cancelPeripheralConnection}, the cause will be detailed in the <i>error</i> parameter. Once this method has been
     *                      called, no more methods will be invoked on <i>peripheral</i>'s <code>CBPeripheralDelegate</code>.
     *
     */
    @available(iOS 5.0, *)
    optional func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)

    
    /**
     *  @method centralManager:connectionEventDidOccur:forPeripheral:
     *
     *  @param central      The central manager providing this information.
     *  @param event        The <code>CBConnectionEvent</code> that has occurred.
     *  @param peripheral   The <code>CBPeripheral</code> that caused the event.
     *
     *  @discussion         This method is invoked upon the connection or disconnection of a peripheral that matches any of the options provided in {@link registerForConnectionEventsWithOptions:}.
     *
     */
    @available(iOS 13.0, *)
    optional func centralManager(_ central: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral)

    
    /**
     *  @method centralManager:didUpdateANCSAuthorizationForPeripheral:
     *
     *  @param central      The central manager providing this information.
     *  @param peripheral   The <code>CBPeripheral</code> that caused the event.
     *
     *  @discussion         This method is invoked when the authorization status changes for a peripheral connected with {@link connectPeripheral:} option {@link CBConnectPeripheralOptionRequiresANCS}.
     *
     */
    @available(iOS 13.0, *)
    optional func centralManager(_ central: CBCentralManager, didUpdateANCSAuthorizationFor peripheral: CBPeripheral)
}

如果连接成功,就会有成功的回调,到这里蓝牙连接获取成功的,紧接着开始搜索蓝牙的服务,通过调用

   func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        peripheral.delegate = self // 设置 CBPeripheralDelegate 
        peripheral.discoverServices(nil) // 搜索服务
    }

发现服务,会有CBPeripheralDelegate中的回调,然后继续从服务中寻找特征

    /** 发现服务 */
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        for service: CBService in peripheral.services! {
            print(TAG + "外设中的服务有:\(service)")
        }
        
        // 根据UUID寻找服务中的特征
        for service in peripheral.services! {
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }

   
    /** 发现特征 */
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        for characteristic: CBCharacteristic in service.characteristics! {
            print(TAG + "外设中的特征有:\(characteristic)")
            print(TAG + "外设中的特征有UUID:\(characteristic.uuid.uuidString)")
            if characteristic.uuid.uuidString == "2A25" {  //获取mac addr 特征
                peripheral.setNotifyValue(true, for: characteristic)
                // 读取特征值,主要返回mac地址
                peripheral.readValue(for: characteristic)
            }
        }
        
        let characteristic = service.characteristics?.last
        
        peripheral.setNotifyValue(true, for: characteristic!)
        
        peripheral.readValue(for: characteristic!)
        
        保留//匹配蓝牙对应特征
        mCharacteristicDict[peripheral] = characteristic
        
    }

 /** 订阅状态 */
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        if let error = error {
            print(TAG + "订阅失败: \(error)")
            return
        }
        if characteristic.isNotifying {
            print(TAG + "avc" + "订阅成功")
            
            if mCurAddress != "" && mPeripheralDict[mCurAddress] == peripheral && characteristic == mCharacteristicDict[peripheral] {
                connetSuc()
            } else if mCurAddress == "" {
                for (addr, per) in mPeripheralDict {
                    if per == peripheral {
                        mNotifyDict[addr] = true
                        break
                    }
                }
            }
        } else {
            print(TAG + "取消订阅")
        }
    }
    
    /** 接收到数据 */
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if !(characteristic.value != nil) {
            return
        }
        let data = characteristic.value!
        //let message = CommonTool.dataToHexString(data)
        let message = String(bytes: data, encoding: String.Encoding.utf8)!
        // 接受到的数据,对数据进行处理
    }
    
    /** 写入数据 */
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        print(TAG + "写入数据")
    }

最后是建立成功发送数据

        self.mCurPeripheral?.writeValue(data, for: self.mCurCharacteristic!, type: .withoutResponse)

这样基本就实现了具体特征值的一些基础通讯了,通讯过程的交互协议根据自己的业务需要去定义
后续我会把Android的蓝牙通讯也梳理一遍,敬请期待,Android相对比较复杂

相关文章

  • iOS蓝牙连接使用特征值通讯

    蓝牙通讯,今天我们将低功耗的BLE通讯,也就是使用特征值的通讯,该通讯的特点是低功耗,但是其实经常不小心就没电了。...

  • iOS 开发-蓝牙之GameKit框架(iOS7过期)

    蓝牙GameKit简介: 1.实现蓝牙设备之间的通讯;2.只能使用在iOS设备之间同一个应用内连接;3.从iOS7...

  • iOS蓝牙开发

    蓝牙属于近场通讯中的一种,iOS 中使用Core Bluetooth 框架实现蓝牙通信, Core Bluetoo...

  • iOS蓝牙连接读取和写入信息(二)

    蓝牙读取信息过程:连接-查询服务-发现服务、搜索该服务包含的特征值-发现特征值-读取特征值(读取所需外设信息,包含...

  • Android 蓝牙开发

    近期的项目涉及到蓝牙通讯,于是就整理了一下蓝牙的通讯机制的知识点。蓝牙通讯主要是配对和连接两个过程。 配对和连接是...

  • iOS开发蓝牙

    iOS蓝牙模块支持BLE4.0设备通讯。 在使用蓝牙的过程中,如果是iOS10及以上机型需要在info.plist...

  • iOS蓝牙开发

    iOS蓝牙模块支持BLE4.0设备通讯。 在使用蓝牙的过程中,如果是iOS10及以上机型需要在info.plist...

  • ionic中实现BLE的基本功能和注意事项

    在项目中安装BLE插件 扫描蓝牙设备 扫描蓝牙只能获取到 连接蓝牙设备 读取特征值有Read的属性的内容 写数据 ...

  • iOS蓝牙开发(三):App作为外设被连接的实现

    iOS蓝牙开发(三):App作为外设被连接的实现 iOS蓝牙开发(三):App作为外设被连接的实现

  • Android蓝牙权限

    1. 蓝牙权限 蓝牙连接和通讯需要获取相关的蓝牙权限BLUETOOTH和BLUETOOTH_ADMIN。 蓝牙权限...

网友评论

      本文标题:iOS蓝牙连接使用特征值通讯

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