代碼完整蚁孔,只要用自己 設(shè)備的名字 跟 特征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?
///設(shè)備名
let Cperipheral_name = "M***** "
///服務(wù)UUID
let Cserve_01_uuid = "38*"
let Cserve_02_uuid = "26*"
///特征UUID
let Ccharacteristic_01_01_uuid = "3***"
let Ccharacteristic_02_01_uuid = "2***"
注:每個設(shè)備的服務(wù)與特征數(shù)量都不同
}
extension TTBluetoothManger{
///啟用藍(lán)牙,搜索鏈接設(shè)備
///在控制器中調(diào)用即可進(jìn)行整個流程
func bluetoohStar() {
self.centralManager.delegate = self
}
func printShow(str:String) {
print("=====================================")
print("| \(str) |")
print("-------------------------------------")
}
///App向設(shè)備寫入數(shù)據(jù)時調(diào)用次方法
func deviceStartWriteValue(_ characteristic: CBCharacteristic) {
///這是我自己設(shè)備的寫入數(shù)據(jù)
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")
///掃描設(shè)備
central.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey:NSNumber.init(value: false)])
case .poweredOff:
print("CBCentralManager state:", "poweredOff")
default:
print("未知錯誤")
}
}
///發(fā)現(xiàn)設(shè)備
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
///連接設(shè)備
if let _ = self.currentPeripheral{
central.stopScan()
central.connect(self.currentPeripheral!, options: nil)
}
}
}
///連接設(shè)備成功
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
printShow(str: "連接成功")
self.currentPeripheral = peripheral
peripheral.delegate = self
//開始尋找Services。傳入nil是尋找所有Services
peripheral.discoverServices(nil)
}
///連接設(shè)備失敗
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{
///尋找服務(wù)
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
printShow(str: "搜索服務(wù)")
if error != nil{ print("服務(wù)異常:",error.debugDescription);return}
guard let pservices = peripheral.services else {return}
for ser in pservices {
print("[服務(wù)的UUID] \(ser.uuid)")
//在感興趣的服務(wù)中尋找感興趣的特征
if ser.uuid.uuidString == Cserve_01_uuid || ser.uuid.uuidString == Cserve_02_uuid{
self.currentPeripheral?.discoverCharacteristics(nil, for: ser)
}
}
}
/// 從感興趣的服務(wù)中,確認(rèn) 我們所發(fā)現(xiàn)感興趣的特征
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
printShow(str: "確認(rèn)特征")
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)
// 訂閱關(guān)于感興趣特征的持續(xù)通知;
// “當(dāng)你啟用特征值的通知時欧瘪,外圍設(shè)備調(diào)用……
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: - 檢測向外設(shè)寫數(shù)據(jù)是否成功
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
if error != nil {
printShow(str: "寫數(shù)據(jù)失敗!!!")
}else{printShow(str: "??寫入數(shù)據(jù)成功??")}
}
// 接收外設(shè)發(fā)來的數(shù)據(jù) 每當(dāng)一個特征值定期更新或者發(fā)布一次時宝与,我們都會收到通知岖沛;
// 閱讀并解譯我們訂閱的特征值
// MARK: - 獲取外設(shè)發(fā)來的數(shù)據(jù)
// 注意罢坝,所有的廓握,不管是 read , notify 的特征的值都是在這里讀取
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
printShow(str: "接收數(shù)據(jù)")
if (characteristic.value != nil) {
let data = characteristic.value
let mod = Model()
mod.read_analyzeData(fromData: data!)
}
}
//接收characteristic信息 //MARK: - 特征的訂閱狀體發(fā)生變化
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];
///剩余使用次數(shù)
let surplus = byteArr[14];
print("[","時 = ",hour);
print("分 = ",min);
print("秒 = ",sec);
print("水分 = ",waterValue);
print("油分 = ",oilValue);
print("倒計時標(biāo)志 = ",countdownFlag);
print("工作狀態(tài) = ",workStatus);
print("剩余次數(shù) = ",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進(jìn)制的轉(zhuǎn)換
//16進(jìn)制類型的字符串[A-F,0-9]和Data之間的轉(zhuǎn)換可以使用下面的方法。如果是包含=之類的可以直接用字符串轉(zhuǎn)換Data即可
///16進(jìn)制字符串轉(zhuǎn)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轉(zhuǎn)16進(jìn)制字符串
func hexString() -> String {
return map { String(format: "%02x", $0) }.joined(separator: "").uppercased()
}
}
···