Swift项目中快速集成蓝牙(Ble4.0)模块

引言

此篇为实践篇,理论篇请见App蓝牙通讯技术

背景

Swift项目中简单快速的集成iOS蓝牙模块,对蓝牙的操作封装了一个蓝牙管理类。(EasyBleManager)

功能如下

  • 同步获取蓝牙状态,使用更加的灵活和便捷
  • 扫描设备和连接设备
  • 可配置指定的设备名称、设备可被发现的Service
  • 扫描和连接超时设置
  • 添加设备准备就绪状态,设备连接成功后,并不能直接读写操作,要等设备准备就绪后,就随时可以读写操作
  • 方便简单的读写操作
  • 开启和关闭调试日志

具体用法

配置需要操作的特性uuid

let DeviceVersion = "XXXX"
let DeviceMode = "XXXX"

检查蓝牙是否可用

if EasyBleManager.shareInstance.isBleEnable {
    print("蓝牙可用")
} else {
    print("蓝牙不可用")
}

获取连接上的设备

let connectedDevice = EasyBleManager.shareInstance.connectedDevice()

系统蓝牙状态变化时回调

EasyBleManager.shareInstance.bleStateChangeBlock = {(state) in
    print("蓝牙状态:\(state)")
}

开启调试日志信息

EasyBleConfig.enableLog = true //默认未启动调试日志

配置可扫描到的设备名称/设备可被发现的Service

 EasyBleConfig.acceptableDeviceNames = ["XXXX"] //默认接受所有设备
 EasyBleConfig.acceptableDeviceServiceUUIDs = ["XXXX"] //默认发现设备所有的Service

扫描超时回调

EasyBleManager.shareInstance.bleScanTimeoutBlock = {
    print("扫描超时")
}

连接超时回调

EasyBleManager.shareInstance.bleConnectTimeoutBlock = {
    print("连接超时")
}

扫描成功回调

EasyBleManager.shareInstance.bleScanSuccessBlock = {(_) in
    print("扫描设备成功")
}

设备连接成功回调,此时设备还不能直接去读写操作

EasyBleManager.shareInstance.bleConnectSuccessBlock = {(_) in
    print("设备连接成功")
}

设备准备就绪回调,此时可以读写操作

EasyBleManager.shareInstance.deviceReadyBlock = {(_) in
    print("设备已经准备就绪成功")
}

扫描设备/停止扫描

EasyBleManager.shareInstance.scanForDevices()//扫描设备
EasyBleManager.shareInstance.stopScan()//停止扫描

连接设备

EasyBleManager.shareInstance.connectDevice(device)

读取数据

device?.readDeviceInfo("设备版本号特性uuid", complete: { (value) in
    var versionString = ""
    if value != nil {
        versionString = String.init(data: value!, encoding: String.Encoding.utf8) ?? ""
    }
    print("设备版本号:\(versionString)")
})

写入数据

let bytes: [UInt8] = [0x10]
device?.writeDevice("设备特性uuid", bytes: bytes) { (success) in
    if success {
        print("写入成功")
    } else {
        print("写入失败")
    }
}

遇到的一些坑

1 蓝牙初始化后,直接去扫描设备,无法扫描到设备
方法:

蓝牙初始化后,蓝牙状态此时是unknown状态,要等系统回调updateManagerState后,蓝牙才进行正常状态,所以扫描方法应放到

func updateManagerState(_ central: CBCentralManager?) {
   switch central.state {
        case .poweredOn:
   }
}

2 因为第一个坑的原因,所以扫描设备方法要放到蓝牙状态回调方法中去,使用起来特别的不方便
方法:

把获取系统蓝牙状态方法设计成同步方法,这里使用了DispatchGroup类,具体的请见源码

3 能扫描到设备,无法连接到设备,连接成功和失败的接口都没有回调
方法:

把扫描到的peripheral保存起来,因为peripheral没有被引用的时候,设备连接成功后,会自动断开,并且不会进入回调方法。

array.append(peripheral)

4 连接成功后,读写数据失败
方法:

设备连接成功后,此时设备里的服务和特性值并没有被发现,直接去读写操作是不会成功的,要等需要访问的服务和特性值被发现后,才能对这个特性值读写操作。
这里我设计了一个设备准备就绪回调方法,当设备准备就绪时,就可以随时读写任意的服务和特性了。

BleManager.shareInstance.deviceReadyBlock = {(_) in
    print("设备已经准备就绪,随时可以读写操作")
}

具体的请见源码

最后

在使用过程中如果有任何问题和建议都可以随时联系我
我的邮箱 344185723@qq.com
源码地址 EasyBleManager
愿大家都可以开开心心的写代码!


版权声明:本文为paul250670原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。