蓝牙

作者: 纳兰沫 | 来源:发表于2019-11-20 09:24 被阅读0次

中心设备

import UIKit
import CoreBluetooth

let heartRateServiceUUID = CBUUID(string: "180D")
let controlPointCharacteristicUUID = CBUUID(string: "2A39")//可写特征
let sensorLocationCharacteristicUUID = CBUUID(string: "2A38")//可读特征
let measurementCharacteristicUUID = CBUUID(string: "2A37")//可通知特征

class ViewController: UIViewController {

    @IBOutlet weak var writeCharacteristicTextField: UITextField!
    @IBOutlet weak var sensorLocationLabel: UILabel!
    @IBOutlet weak var heartRateLabel: UILabel!
    var centralManager: CBCentralManager!
    var heartRatePeripheral: CBPeripheral!
    var controlPointCharacteristic: CBCharacteristic?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //创建中心设备管理器
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }


    @IBAction func write(_ sender: UIButton) {
        
        guard let controlPointCharacteristic = controlPointCharacteristic else {
            return
        }
        heartRatePeripheral.writeValue(writeCharacteristicTextField.text!.data(using: .utf8)!, for: controlPointCharacteristic, type: .withResponse)
    }
}

extension ViewController: CBCentralManagerDelegate {
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("未知")
        case .resetting:
            print("蓝牙重置中")
        case .unsupported:
            print("本机不支持BLE")
        case .unauthorized:
            print("未授权")
        case .poweredOff:
            print("蓝牙未开始")
        case .poweredOn:
            print("蓝牙开启")
            //扫描外设
            central.scanForPeripherals(withServices: [heartRateServiceUUID])
        @unknown default:
            print("来自未来的错误")
        }
    }
    
    //发现外设
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        //advertisementData 广播数据 RSSI 信号强度
        heartRatePeripheral = peripheral
        central.stopScan()
        central.connect(peripheral)
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        
        peripheral.delegate = self
        peripheral.discoverServices([heartRateServiceUUID])
    }
    
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        
    }
    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        //重连
        central.connect(peripheral)
    }
}


extension ViewController: CBPeripheralDelegate {
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        
        if let error = error {
            print("没找到服务的原因 \(error.localizedDescription)")
        }
        guard let service = peripheral.services?.first else { return }
        peripheral.discoverCharacteristics([
            controlPointCharacteristicUUID,
            sensorLocationCharacteristicUUID,
            measurementCharacteristicUUID
            ], for: service)
    }
    
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        
        if let error = error {
            print("没找到特征的原因 \(error.localizedDescription)")
        }
        
        guard let characteristics = service.characteristics else { return }
        for characteristic in characteristics {
            if characteristic.properties.contains(.write){
                
                controlPointCharacteristic = characteristic
                peripheral.writeValue("100".data(using: .utf8)!, for: characteristic, type: .withResponse)
            }
            if characteristic.properties.contains(.read){
                //读取外设的数据 (其实就是读取外设里面某个特征的值value) 立即调用 didUpdateValueFor
                //若读取成功则可以通过characteristic.value取出值
                //适合读取静态值
                peripheral.readValue(for: characteristic)
            }
            if characteristic.properties.contains(.notify){
                //订阅
                //订阅外设的某个数据(某个特征的值) 达到实时更新数据的目的
                //订阅后会先调用didUpdateNotificationStateFor
                //若订阅成功 则d每当特征值发生变化时都会 调用 didUpdateValueFor
                //适合读动态值  一直在变化的值
                peripheral.setNotifyValue(true, for: characteristic)
            }
            
            //这里可以继续发现特征下面的描述
            //peripheral.discoverDescriptors(for: characteristic)
            //之后会立即调用diddiscover...获取描述值
        }
    }
    
    //写入之后的回调
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        
        if let error = error {
            print("写入失败的原因是 \(error.localizedDescription)")
            return
        }
        
        print("写入成功")
    }
    
    //查看是否订阅成功 订阅状态
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        
        if let error = error {
            print("订阅失败的原因是 \(error.localizedDescription)")
            return
        }
    }
    
    //读取数据的回调
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        
        if let error = error {
            print("读取失败的原因是 \(error.localizedDescription)")
            return
        }
        
        switch characteristic.uuid {
        case sensorLocationCharacteristicUUID:
            //赋值
            sensorLocationLabel.text = String(data: characteristic.value!, encoding: .utf8)
        case measurementCharacteristicUUID:
            guard let heartRate = Int(String(data: characteristic.value!, encoding: .utf8)!) else { return }
            heartRateLabel.text = "\(heartRate)"
        default:
            break
        }
    }
}

外围设备

import UIKit
import CoreBluetooth
//在终端输入uuidgen 会出现uuid
let serviceUUID = CBUUID(string: "CADB235E-49F0-438C-9BF2-7EA89809A21E")
let writeUUID = CBUUID(string: "88B1AE2F-7B9C-4FDB-94BD-45BDCF626342")
let readUUID = CBUUID(string: "C174BDCC-1D28-4A78-BC40-EFFD545AE96D")
let notifyUUID = CBUUID(string: "649497CD-43D3-4211-A3A4-7B7207FF2823")

class ViewController: UIViewController {

    @IBOutlet weak var writeLabel: UILabel!
    @IBOutlet weak var readLabel: UILabel!
    @IBOutlet weak var notifyLabel: UILabel!
    
    var peripjeralManager: CBPeripheralManager!
    var write: CBMutableCharacteristic!
    var notify: CBMutableCharacteristic!
    var timer: Timer?
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        
        peripjeralManager = CBPeripheralManager(delegate: self, queue: nil)
    }

}

extension ViewController: CBPeripheralManagerDelegate {
    
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        switch peripheral.state {
        case .unknown:
            print("未知")
        case .resetting:
            print("蓝牙重置中")
        case .unsupported:
            print("本机不支持BLE")
        case .unauthorized:
            print("未授权")
        case .poweredOff:
            print("蓝牙未开始")
        case .poweredOn:
            print("蓝牙开启")
           //primary 创建的服务是否是主服务
           let service = CBMutableService(type: serviceUUID, primary: true)
           //创建特征
            //value 不写死 以便可以修改
           write = CBMutableCharacteristic(type: writeUUID, properties: .write, value: nil, permissions: .writeable)
           let read = CBMutableCharacteristic(type: readUUID, properties: .read, value: nil, permissions: .readable)
           notify = CBMutableCharacteristic(type: notifyUUID, properties: .notify, value: nil, permissions: .readable)
           //把特征加入服务
           service.characteristics = [write,read,notify]
           //把服务加入外设
            peripjeralManager.add(service)
            //开始广播
            peripjeralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [serviceUUID]])
        @unknown default:
            print("来自未来的错误")
        }
    }
    
    //添加服务
    func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
        
        if let error = error {
            print("无法添加服务的的原因 \(error.localizedDescription)")
        }
    }
    //开始广播后
    func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
        
        if let error = error {
            print("无法开始广播的的原因 \(error.localizedDescription)")
        }
    }
    
    //当中心设备发送(对一个或多个特征值的)写入请求时
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        let request = requests[0]
        if request.characteristic.properties.contains(.write){
            //给当前请求的特征值改值
            write.value = request.value
            //显示到视图
            writeLabel.text = String(data: request.value!, encoding: .utf8)
            //给中心设备反馈 以便中心设备可以触发一些delegate方法
            peripheral.respond(to: request, withResult: .success)
        }else{
            peripheral.respond(to: request, withResult: .writeNotPermitted)
        }
        
    }
    //当中心设备发送数据(某个特征的值)请求时
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {

        if request.characteristic.properties.contains(.read){
            //给request下的value赋值当前请求特征的值 然后随着respond带到中心设备去
            //request.value = request.characteristic.value
            //这里用文本框中的数据模拟某个特征的值
            request.value = readLabel.text!.data(using: .utf8)
            writeLabel.text = String(data: request.value!, encoding: .utf8)
            peripheral.respond(to: request, withResult: .success)
        }else{
            peripheral.respond(to: request, withResult: .readNotPermitted)
        }
    }
    
    //当中心设备订阅了某个特征值时
    func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
        
       updateNotifyValue()
    
    }
    
    //传输队列有了剩余空间时
    func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
        updateNotifyValue()
    }
    
    //当中心设备取消订阅某个特征值时
    func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
        
        timer?.invalidate()
    }
    
    func updateNotifyValue() {
        
        //用计时器模拟外设数据的实时变动
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
            
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy年MM月dd日 HH时mm分ss秒"
            let dateStr = dateFormatter.string(from: Date())
            
            self.notifyLabel.text = dateStr
            //更新特征值 给一个或多个(第三个参数指定为nil)订阅这个特征的中心设备发送实时数据
            //返回bool true -> 发送成功 false -> 传输队列已满
            //如果待会有了空间 则调用peripheralManagerIsReady 可在里面再次发送数据
            self.peripjeralManager.updateValue(dateStr.data(using: .utf8)!, for: self.notify, onSubscribedCentrals: nil)
        }
    }
    
    
}

相关文章

网友评论

      本文标题:蓝牙

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