Swift4.2使用CoreBluetooth進行藍牙設備連接2019-04-17

代碼完整,只要用自己 設備的名字 跟 特徵uuid 即可看到效果

import UIKit
import CoreBluetooth

class PeripheralInfo {
    var serviceUUID: CBUUID?
    var characteristics: [CBCharacteristic]?
}
class TTBluetoothManger:NSObject {

    static var share =  TTBluetoothManger()
    private override init(){}
    
    lazy var centralManager:CBCentralManager = {
        let c =  CBCentralManager.init()
        c.delegate = self
        return c
    }()
    
    var currentPeripheral:CBPeripheral?
    var currentCharacteristic_01_01:CBCharacteristic?
    var currentCharacteristic_02_01:CBCharacteristic?

    ///設備名
    let Cperipheral_name = "M*****  "
    
    ///服務UUID
    let Cserve_01_uuid = "38*"
    let Cserve_02_uuid = "26*"
    
    ///特徵UUID
    let  Ccharacteristic_01_01_uuid = "3***"
    let  Ccharacteristic_02_01_uuid = "2***"

  注:每個設備的服務與特徵數量都不同

}

extension TTBluetoothManger{

    ///啓用藍牙,搜索鏈接設備
    ///在控制器中調用即可進行整個流程
    func bluetoohStar() {
        self.centralManager.delegate = self
    }
    
    func printShow(str:String) {
        
        print("=====================================")
        print("|             \(str)                |")
        print("-------------------------------------")
    }
    
    ///App向設備寫入數據時調用次方法
    func deviceStartWriteValue(_ characteristic: CBCharacteristic) {
        
        ///這是我自己設備的寫入數據
        let data = Data.init(bytes:[
            0x01,0xfe,0x00,0x00,
            0x23,0x33,0x10,0x00,
            0x64,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00])
        currentPeripheral!.writeValue(data, for: characteristic, type: CBCharacteristicWriteType.withResponse)
    }
    
}

extension TTBluetoothManger:CBCentralManagerDelegate{
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        
        switch central.state {
        case .unknown:
            print("CBCentralManager state:", "unknown")
        case .resetting:
            print("CBCentralManager state:", "resetting")
        case .unsupported:
            print("CBCentralManager state:", "unsupported")
        case .unauthorized:
            print("CBCentralManager state:", "unauthorized")
        case .poweredOn:
            print("CBCentralManager state:", "poweredOn")
            ///掃描設備
            central.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey:NSNumber.init(value: false)])
            
        case .poweredOff:
            print("CBCentralManager state:", "poweredOff")
        default:
            print("未知錯誤")
        }
    }
    
    ///發現設備
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        print("---------------------START---------------------")
        print("peripheral.name = \(peripheral.name ?? "搜索失敗!")")
        if peripheral.name != nil{
            guard peripheral.name == "DMK28  " else{return}
            print("peripheral.name = \(peripheral.name!)")
            print("central = \(central)")
            print("peripheral = \(peripheral)")
            print("RSSI = \(RSSI)")
            print("advertisementData = \(advertisementData)")
            self.currentPeripheral = peripheral
            
            ///連接設備
            if let _ = self.currentPeripheral{
                central.stopScan()
                central.connect(self.currentPeripheral!, options: nil)
            }
            
        }
    }
    
    ///連接設備成功
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        
        printShow(str: "連接成功")
        self.currentPeripheral = peripheral
        peripheral.delegate = self
        //開始尋找Services。傳入nil是尋找所有Services
        peripheral.discoverServices(nil)
    }
    
    ///連接設備失敗
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
    
        printShow(str: "連接失敗:\(error.debugDescription)")
    }

    ///斷開連接
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        printShow(str: "斷開連接")
        
        ///可重新掃描
    }
    
    
}

extension TTBluetoothManger:CBPeripheralDelegate{
    
    ///尋找服務
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        printShow(str: "搜索服務")
        if error != nil{  print("服務異常:",error.debugDescription);return}
        guard let pservices = peripheral.services else {return}
        for ser in pservices {
            print("[服務的UUID] \(ser.uuid)")
            //在感興趣的服務中尋找感興趣的特徵
            if ser.uuid.uuidString == Cserve_01_uuid || ser.uuid.uuidString == Cserve_02_uuid{
                self.currentPeripheral?.discoverCharacteristics(nil, for: ser)
            }
            
        }
    }

    /// 從感興趣的服務中,確認 我們所發現感興趣的特徵
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        printShow(str: "確認特徵")

        if error != nil{  print("特徵異常:",error.debugDescription);return}
        guard let serviceCharacters = service.characteristics else {return}
        for characteristic in serviceCharacters {
            let characteristic_uuid = characteristic.uuid
            print("<特徵UUID>",characteristic_uuid)

            // 訂閱關於感興趣特徵的持續通知;
            // “當你啓用特徵值的通知時,外圍設備調用……
            if characteristic_uuid.uuidString == Ccharacteristic_01_01_uuid{
                self.currentCharacteristic_01_01 = characteristic
                peripheral.setNotifyValue(true, for: characteristic)
            }
            //讀取感興趣的特徵
            if characteristic_uuid.uuidString == Ccharacteristic_02_01_uuid{
                self.currentCharacteristic_02_01 = characteristic
                peripheral.readValue(for: characteristic)

            }
        }
    }
    
    //MARK: - 檢測向外設寫數據是否成功
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {
            printShow(str: "寫數據失敗!!!")
        }else{printShow(str: "🌺寫入數據成功🌺")}
        
    }
    
    // 接收外設發來的數據 每當一個特徵值定期更新或者發佈一次時,我們都會收到通知;
    // 閱讀並解譯我們訂閱的特徵值
    // MARK: - 獲取外設發來的數據
    // 注意,所有的,不管是 read , notify 的特徵的值都是在這裏讀取
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        printShow(str: "接收數據")
        if (characteristic.value != nil) {
            let data = characteristic.value
            
            let mod = Model()
            mod.read_analyzeData(fromData: data!)
        }
    }
    
    //接收characteristic信息    //MARK: - 特徵的訂閱狀體發生變化
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        print("========特徵的訂閱狀體變化========")
        printShow(str: characteristic.uuid.uuidString)
        
    }
    
}


class Model: NSObject {
    
    var waterArr = [Double]()
    var oilArr = [Double]()
    var lastwaterArr = [Double]()
    var lastoilArr = [Double]()
    
    var min:UInt8 = 0
    var sec:UInt8 = 0
    var waterValue:UInt8 = 0
    var oilValue:UInt8 = 0
    var countdownFlag:UInt8 = 0
    var workStatus:UInt8 = 0
    var surplus:UInt8 = 0
    var timeString:String = "00:00"
    var isPush = false
    
    var waterValue_100: Int = 0
    var oilValue_100:Int = 0
    
    func read_analyzeData(fromData data:Data) -> Void {
        
        let byteArr = data.bytes
        print(byteArr);
        if byteArr.count > 0{
            let hour = byteArr[7];
            let min = byteArr[8];
            let sec = byteArr[9];
            
            let waterValue = byteArr[10];
            let oilValue = byteArr[11];
            
            let countdownFlag = byteArr[12];
            let workStatus = byteArr[13];
            ///剩餘使用次數
            let surplus = byteArr[14];
            
            
            print("[","時 = ",hour);
            print("分 = ",min);
            print("秒 = ",sec);
            print("水分 = ",waterValue);
            print("油分 = ",oilValue);
            print("倒計時標誌 = ",countdownFlag);
            print("工作狀態 = ",workStatus);
            print("剩餘次數 = ",surplus,"]");
            
            var minString = "\(min)"
            var secString = "\(sec)"
            
            if min < 10 {
                minString = "0" + minString;
            }
            
            if sec < 10 {
                secString = "0" + secString;
            }
            
            let timeString = minString + ":" + secString;
            
            self.min = min;
            self.sec = sec;
            self.waterValue = waterValue;
            self.oilValue = oilValue;
            self.countdownFlag = countdownFlag;
            self.workStatus = workStatus;
            self.surplus = surplus;
            self.timeString = timeString;
            
            
            let temp_water = Int(waterValue)
            self.waterValue_100 = temp_water
            
            let temp_oil = Int(oilValue)
            self.oilValue_100 = temp_oil;
        }
    }
}










extension Data {
    /// Data -> Array, Dictionary
    ///
    /// - Returns: Array
    func toArray() -> [Any]? {
        
        return toArrayOrDictionary() as? [Any]
    }
    
    /// Data -> Array, Dictionary
    ///
    /// - Returns: Array
    func toDictionary() -> [String:Any]? {
        
        return toArrayOrDictionary() as? [String:Any]
    }
    
    /// Data -> Array, Dictionary
    ///
    /// - Returns: Any
    fileprivate func toArrayOrDictionary() -> Any? {
        
        do {
            
            let data = try JSONSerialization.jsonObject(with: self, options: JSONSerialization.ReadingOptions.allowFragments)
            
            return data
        } catch let _ {
            return nil
        }
    }
    
    public var bytes: Array<UInt8> {
        return Array(self)
    }
}

extension String {
    
    //16進制的轉換
    //16進制類型的字符串[A-F,0-9]和Data之間的轉換可以使用下面的方法。如果是包含=之類的可以直接用字符串轉換Data即可

    ///16進制字符串轉Data
    func hexData() -> Data? {
        var data = Data(capacity: count / 2)
        let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
        regex.enumerateMatches(in: self, range: NSMakeRange(0, utf16.count)) { match, flags, stop in
            let byteString = (self as NSString).substring(with: match!.range)
            var num = UInt8(byteString, radix: 16)!
            data.append(&num, count: 1)
        }
        guard data.count > 0 else { return nil }
        return data
    }
    
    func utf8Data()-> Data? {
        return self.data(using: .utf8)
    }
    
}

extension Data {
    ///Data轉16進制字符串
    func hexString() -> String {
        return map { String(format: "%02x", $0) }.joined(separator: "").uppercased()
    }
}

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