关于BLE开发(swift)

随着智能硬件的发展,出现了很多智能硬件APP,比如配合运动手环的计步APP、配合体重秤的APP等。最近简单研究了一下
1.BLE
最新的蓝牙4.0以其低功耗著称,所以一般也叫BLE(Bluetooth Low Energy)。iOS 有两个框架支持蓝牙与外设连接。一个是 ExternalAccessory,从ios3.0就开始支持,也是在iphone4s出来之前用的比较多的一种模式,但是它有个不好的地方,External Accessory需要拿到苹果公司的MFI认证。另一个框架则是本文要介绍的CoreBluetooth,在iphone4s开始支持,专门用于与BLE设备通讯(因为它的API都是基于BLE的)。这个不需要MFI,并且现在很多蓝牙设备都支持4.0,所以也是在IOS比较推荐的一种开发方法。蓝牙4.0协议从iPhone 4s 以上开始支持, iPad 3.0以上 iPad Mini 及以上版本支持.
Core Bluetooth framework可以让你的iOS和Mac apps与Bluetooth Low Energy 设备(简写BLE)交流。这些设备包括心率监测器,数字体温计,等等。Core Bluetooth framework是一个对Bluetooth4.0 specification的抽象,并定义了一系列容易使用的协议来和BLE设备通信。

2.api参考
https://developer.apple.com/reference/corebluetooth
CBPeripheral 蓝牙外设,比如蓝牙手环、蓝牙心跳监视器、蓝牙打印机。
CBCentralManager 蓝牙外设管理中心,与手机的蓝牙硬件模板关联,可以获取到手机中蓝牙模块的一些状态等,但是管理的就是蓝牙外设。
CBService 蓝牙外设的服务,每一个蓝牙外设都有0个或者多个服务。而每一个蓝牙服务又可能包含0个或者多个蓝牙服务,也可能包含0个或者多个蓝牙特性。
CBCharacteristic 每一个蓝牙特性中都包含有一些数据或者信息。
下面看demo,系统的方法如果直接拿出来用,感觉过于繁琐,所以我这里封装了一个工具类:

import CoreBluetooth

protocol BLEToolDelegate : NSObjectProtocol{
    //发现设备
    func didDiscoverPeripheral(_ peripheral: CBPeripheral!)
    //读取数据
    func readData(data:Data!)
}

class BLETool: NSObject,CBCentralManagerDelegate,CBPeripheralDelegate {


    //添加属性
    private var centralManager: CBCentralManager!
    private var peripheral: CBPeripheral!
    private var writeCharacteristic: CBCharacteristic!
    //保存收到的蓝牙设备
    var services:Array = Array()
    weak var delegate : BLEToolDelegate!


    override init() {
        super.init()
        self.centralManager = CBCentralManager.init(delegate: self, queue: nil)
    }

    class func shared() -> BLETool{
        struct Static {
            static let instance: BLETool = BLETool()
        }
        return Static.instance
    }
    /** 停止扫描 **/
    func stopScan() {
        self.centralManager.stopScan()
    }
    //我们需要实现CBCentralManagerDelegate协议来允许代理监测发现,连接,检索设备.
    //CBCentralManager对象初始化完毕后自动调用此方法;
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOff:
            print("蓝牙已关闭")
            break
        case .poweredOn:
            print("蓝牙已打开,请扫描外设")
            centralManager.scanForPeripherals(withServices: nil, options:[CBCentralManagerScanOptionAllowDuplicatesKey: false])
            break
        case .resetting:
            print("正在重置状态")
            break
        case .unauthorized:
            print("无权使用蓝牙低功耗")
            break
        case .unknown:
            print("未知设备")
            break
        case .unsupported:
            print("此设备不支持BLE")
            break
        }
    }

    //这个方法在搜索的过程中,每发现一个peripheral(外围设备)就调用此方法一次
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if !self.services.contains(peripheral) {
            self.services.append(peripheral)
            if self.delegate != nil {
                self.delegate.didDiscoverPeripheral(peripheral)
            }
        }
    }
    //连接外设成功,开始发现服务
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        //停止扫描外设
        self.centralManager.stopScan()
        self.peripheral = peripheral
        self.peripheral.delegate = self
        //发现某些服务,若参数为nil则发现所有服务.
        self.peripheral.discoverServices(nil)
    }
    //连接外设失败
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("连接外设失败===\(String(describing: error))")
    }
    //成功断开链接后
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        print("连接已断开")
    }
    //我们需要实现CBPeripheralDelegate协议来监测发现,搜索与远程设备service的交互.
    //成功发现服务,请求周边去寻找它的服务所列出的特征,当每发现一个服务时,调用下面方法一次.
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if error != nil {
            print("连接外设失败===\(String(describing: error))")

            return
        }
        for service in peripheral.services! {
            peripheral.discoverCharacteristics(nil, for: service)
        }
    }
    //成功发现特征,对于每个服务的每个特征被发现时都调用此方法一次
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        print("发现特征的服务:\(service.uuid.data)   ===  服务UUID:\(service.uuid)")
        if error != nil {
            print("发现错误的特征:\(String(describing: error?.localizedDescription))")
            return
        }
        for characteristic in service.characteristics! {
            //罗列出所有特性,看哪些是notify方式的,哪些是read方式的,哪些是可写入的。
            switch characteristic.uuid.description {
            case "FFE1":
                //如果以通知的形式读取数据,则直接发到didUpdateValueForCharacteristic方法处理数据。
                self.peripheral.setNotifyValue(true, for: characteristic)
                break
            case "2A37":
                //通知关闭,read方式接受数据。则先发送到didUpdateNotificationStateForCharacteristic方法,再通过readValueForCharacteristic发到didUpdateValueForCharacteristic方法处理数据。
                self.peripheral.readValue(for: characteristic)
                break
            case "2A38":
                self.peripheral.readValue(for: characteristic)
                break
            case "Battery Level":
                self.peripheral.setNotifyValue(true, for: characteristic)
                break
            case "Manufacturer Name String":
                self.peripheral.readValue(for: characteristic)
                break
            case "AF0BADB1-5B99-43CD-917A-A77BC549E3CC":
                self.writeCharacteristic = characteristic
                self.peripheral.writeValue("特征UUID:AF0BADB1-5B99-43CD-917A-A77BC549E3CC".data(using: .utf8)!, for: characteristic, type: .withoutResponse)
                break
            case "6E400002-B5A3-F393-E0A9-E50E24DCCA9E":
                self.peripheral.readValue(for: characteristic)
                break
            default:
                break
            }
        }
    }
    //获取外设发来的数据,不论是read和notify,获取数据都是从这个方法中读取。
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {
            print("更新数据失败\(String(describing: error?.localizedDescription))")
            return
        }
        let data = characteristic.value
        print("返回的数据是:\(data!)")
        if self.delegate != nil {
            self.delegate.readData(data: data)
        }
    }

    //用于检测中心向外设写数据是否成功
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {
            print("发送数据失败!error信息:\(String(describing: error))")
        }
    }
    /** 写入数据 **/
    func writeValue(data: NSData!){
        self.peripheral.writeValue(data as Data, for: self.writeCharacteristic, type: CBCharacteristicWriteType.withoutResponse)
        print("手机向蓝牙发送的数据为:\(data)")
    }

    /** 连接设备 **/
    func connectPeripheral(_ peripheral: CBPeripheral){
        self.centralManager.connect(peripheral, options: nil);
    }

    /** 主动断开设备 **/
    func cancelPeripheralConnection() {
        if self.peripheral != nil {
            self.centralManager.cancelPeripheralConnection(self.peripheral)
        }
    }

当然这是我初步研究,对这个框架了解的还不够透彻,写的不足之处还请大家见谅!为大家推荐一个github上评分相对较高的三方库,他也是基于CoreBluetooth的封装—https://github.com/coolnameismy/BabyBluetooth

你可能感兴趣的:(常用方法)