随着智能硬件的发展,出现了很多智能硬件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