最近我一直在做蓝牙开发的应用,大家也可能意识到,当下蓝牙开发可谓是越来越火,不论是智能穿戴的兴起还是蓝牙家具,车联网蓝牙等等,很多同学也会接触到蓝牙的项目,我从事蓝牙开发也有一段时间了,经手了两个项目。废话不多说了,先向大家简单的介绍有关蓝牙开发的知识。蓝牙低能耗(BLE),以下介绍的都是围绕iOS的框架展开的。
蓝牙开发分为中心者模式和管理者模式:1.常用的(其实99.99%)就是使用中心者模式作为开发,就是我们手机作为主机,连接蓝牙外设;2.管理者模式,这个基本用到的比较少,我们手机自己作为外设,自己创建服务和特征,然后有其他的设备连接我们的手机。
在做蓝牙开发之前,最好先了解一些概念:
服务(services):蓝牙外设对外广播的必定会有一个服务,可能也有多个,服务下面包含着一些特征,服务可以理解成一个模块的窗口;
特征(characteristic):存在于服务下面的,一个服务下面也可以存在多个特征,特征可以理解成具体实现功能的窗口,一般特征都会有value,也就是特征值,特征是与外界交互的最小单位;
UUID:可以理解成蓝牙上的唯一标识符(硬件上肯定不是这个意思,但是这样理解便于我们开发),为了区分不同的服务和特征,或者给服务和特征取名字,我们就用UUID来代表服务和特征。
蓝牙连接可以大致分为以下几个步骤
1.建立一个Central Manager实例进行蓝牙管理
2.搜索外围设备
3.连接外围设备
4.获得外围设备的服务
5.获得服务的特征
6.从外围设备读数据
7.给外围设备发送数据
其他:提醒
首先是导入框架import CoreBluetooth
必须遵守2个协议
<CBCentralManagerDelegate, CBPeripheralDelegate>
定义中心管理者
fileprivate var centralManager :CBCentralManager!
定义外设
fileprivate var curretPeripheral :CBPeripheral!
1.创建中心设备进行蓝牙管理并设置代理:
func setupBluretooth(){
centralManager = CBCentralManager(delegate: self, queue: nil)
}
//只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case.poweredOff:
print("蓝牙以关闭")
case .unsupported:
print("不支持蓝牙")
case .unknown:
print("蓝牙状态未知")
case .resetting:
print("重置")
case .poweredOn:
print("蓝牙以打开")
//利用中心设备扫描外部设备:
//第一个参数那里表示扫描带有相关服务的外部设备,例如填写@[[CBUUIDUUIDWithString:@"需要连接的外部设备的服务的UUID"]],即表示带有需要连接的外部设备的服务的UUID的外部设备,nil表示扫描全部设备;
central.scanForPeripherals(withServices: nil, options: nil)
// 搜索成功之后,会调用我们找到外设的代理方法
// func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
default:
print("此设备不支持BLE或未打开蓝牙功能,无法作为外围设备.")
}
}
2.搜索外围设备(发现设备),一旦扫描到外部设备,就会进入下列协议中的
/// - parameter central: 中心管理者
/// - parameter peripheral: 外设
/// - parameter advertisementData: 外设携带的数据
/// - parameter RSSI: 外设发出的蓝牙信号强度
func centralManager(_ central: CBCentralManager,didDiscover peripheral: CBPeripheral, advertisementData: [String : Any],rssi RSSI: NSNumber) {
//在这个方法里,我们可以根据我们获取到的硬件的某些条件进行筛选,然后连接我们需要连接的外部设备
print("扫描到的蓝牙设备:\(peripheral)")
//这里我是将扫描到的设备显示在tableView里
//通过点击tableView的cell选择连接到蓝牙设备
//peripherals 是存放 蓝牙设备的数组
peripherals.append(peripheral)
tableView.reloadData()
}
3.连接外围设备
// 中心管理者连接 外设成功
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("连接成功")
//停止扫描
centralManager.stopScan()
// 外围设备设置代理
peripheral.delegate = self
//我们在连接成功的方法中开始扫描外部设备的服务
peripheral.discoverServices(nil)
}
//连接失败
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
print("连接失败")
}
//断开连接
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
print("断开连接")
}
4.获得外围设备的服务
//接着就会跳入发现服务的代理方法中去:
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
print("发现服务:\(peripheral.services)")
for service in peripheral.services! {
//我们在这个方法里面开始扫描服务中的特征:
//serviceUUID 服务UUID(已知)
//kCharacteristicUUID 特证UUID(已知)
let serviceuuid:CBUUID? =
CBUUID.init(string: "\(serviceUUID)")
let characteristicUUID:CBUUID? =
CBUUID.init(string: "\(kCharacteristicUUID)")
if service.uuid == serviceuuid {
peripheral.discoverCharacteristics([characteristicUUID!], for: service)
}
}
}
5.获得服务的特征
//当我们扫描到特征的时候,就会跳入发现特征的协议方法里去
//(这个是比较重要的方法,你在这里可以通过事先知道UUID找到你需要的特征,订阅特征,或者这里写入数据给特征也可以)
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if (error != nil) {
print("error Discovered characteristics for\(service.uuid)---\(error?.localizedDescription)")
}
let serviceuuid:CBUUID? =
CBUUID.init(string: "\(serviceUUID)")
let characteristicUUID:CBUUID? =
CBUUID.init(string: "\(kCharacteristicUUID)")
if service.uuid == serviceuuid {
for characteristic in service.characteristics! {
print(service.uuid)
print(service.uuid.description)
print("\(service.uuid)-----\(characteristic.uuid)")
if characteristic.uuid == characteristicUUID {
//获取Characteristic的值,读数据:
peripheral.readValue(for: characteristic)
//1.给外围设备发送数据(也就是写入数据到蓝牙)
//2.这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦
//3.第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入
//4. 需要注意的是特征的属性是否支持写数据
//peripheral.writeValue(要写入的Data, for: characteristic, type: CBCharacteristicWriteType.withResponse)
}
}
}
//这就读取了特征包含的相关信息,只要读取就会进入下面方法:
}
6.从外围设备读数据
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if (error != nil) {
print("更新特征值时发生错误,错误信息:\(error?.localizedDescription)")
return
}
if characteristic == @"你要的特征的UUID或者是你已经找到的特征" {
//characteristic.value就是你要的数据
}
}
7.给外围设备发送数据(也就是写入数据到蓝牙)
//这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦
peripheral.writeValue(characteristic.value!, for: characteristic, type:.withResponse)
// 最后的type类型有两个,分别是CBCharacteristicWriteWithResponse和CBCharacteristicWriteWithoutResponse;
// 选择第一个,每往硬件写入一次数据都会进入下边的方法
这个方法会告诉我们这次的写入是否成功,但是如果我们不用考虑往硬件写入的数据成功与否的话,选择第二个类型就ok。
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
}
蓝牙开发的基本方法就这么多,有写的不好不对的地方欢迎指正,分享一是为了提升自己和二是希望能对需要的朋友有所帮助!
网友评论