中心设备
import UIKit
import CoreBluetooth
let heartRateServiceUUID = CBUUID(string: "180D")
let controlPointCharacteristicUUID = CBUUID(string: "2A39")//可写特征
let sensorLocationCharacteristicUUID = CBUUID(string: "2A38")//可读特征
let measurementCharacteristicUUID = CBUUID(string: "2A37")//可通知特征
class ViewController: UIViewController {
@IBOutlet weak var writeCharacteristicTextField: UITextField!
@IBOutlet weak var sensorLocationLabel: UILabel!
@IBOutlet weak var heartRateLabel: UILabel!
var centralManager: CBCentralManager!
var heartRatePeripheral: CBPeripheral!
var controlPointCharacteristic: CBCharacteristic?
override func viewDidLoad() {
super.viewDidLoad()
//创建中心设备管理器
centralManager = CBCentralManager(delegate: self, queue: nil)
}
@IBAction func write(_ sender: UIButton) {
guard let controlPointCharacteristic = controlPointCharacteristic else {
return
}
heartRatePeripheral.writeValue(writeCharacteristicTextField.text!.data(using: .utf8)!, for: controlPointCharacteristic, type: .withResponse)
}
}
extension ViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("未知")
case .resetting:
print("蓝牙重置中")
case .unsupported:
print("本机不支持BLE")
case .unauthorized:
print("未授权")
case .poweredOff:
print("蓝牙未开始")
case .poweredOn:
print("蓝牙开启")
//扫描外设
central.scanForPeripherals(withServices: [heartRateServiceUUID])
@unknown default:
print("来自未来的错误")
}
}
//发现外设
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
//advertisementData 广播数据 RSSI 信号强度
heartRatePeripheral = peripheral
central.stopScan()
central.connect(peripheral)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.delegate = self
peripheral.discoverServices([heartRateServiceUUID])
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
//重连
central.connect(peripheral)
}
}
extension ViewController: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let error = error {
print("没找到服务的原因 \(error.localizedDescription)")
}
guard let service = peripheral.services?.first else { return }
peripheral.discoverCharacteristics([
controlPointCharacteristicUUID,
sensorLocationCharacteristicUUID,
measurementCharacteristicUUID
], for: service)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let error = error {
print("没找到特征的原因 \(error.localizedDescription)")
}
guard let characteristics = service.characteristics else { return }
for characteristic in characteristics {
if characteristic.properties.contains(.write){
controlPointCharacteristic = characteristic
peripheral.writeValue("100".data(using: .utf8)!, for: characteristic, type: .withResponse)
}
if characteristic.properties.contains(.read){
//读取外设的数据 (其实就是读取外设里面某个特征的值value) 立即调用 didUpdateValueFor
//若读取成功则可以通过characteristic.value取出值
//适合读取静态值
peripheral.readValue(for: characteristic)
}
if characteristic.properties.contains(.notify){
//订阅
//订阅外设的某个数据(某个特征的值) 达到实时更新数据的目的
//订阅后会先调用didUpdateNotificationStateFor
//若订阅成功 则d每当特征值发生变化时都会 调用 didUpdateValueFor
//适合读动态值 一直在变化的值
peripheral.setNotifyValue(true, for: characteristic)
}
//这里可以继续发现特征下面的描述
//peripheral.discoverDescriptors(for: characteristic)
//之后会立即调用diddiscover...获取描述值
}
}
//写入之后的回调
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
print("写入失败的原因是 \(error.localizedDescription)")
return
}
print("写入成功")
}
//查看是否订阅成功 订阅状态
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
print("订阅失败的原因是 \(error.localizedDescription)")
return
}
}
//读取数据的回调
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
print("读取失败的原因是 \(error.localizedDescription)")
return
}
switch characteristic.uuid {
case sensorLocationCharacteristicUUID:
//赋值
sensorLocationLabel.text = String(data: characteristic.value!, encoding: .utf8)
case measurementCharacteristicUUID:
guard let heartRate = Int(String(data: characteristic.value!, encoding: .utf8)!) else { return }
heartRateLabel.text = "\(heartRate)"
default:
break
}
}
}
外围设备
import UIKit
import CoreBluetooth
//在终端输入uuidgen 会出现uuid
let serviceUUID = CBUUID(string: "CADB235E-49F0-438C-9BF2-7EA89809A21E")
let writeUUID = CBUUID(string: "88B1AE2F-7B9C-4FDB-94BD-45BDCF626342")
let readUUID = CBUUID(string: "C174BDCC-1D28-4A78-BC40-EFFD545AE96D")
let notifyUUID = CBUUID(string: "649497CD-43D3-4211-A3A4-7B7207FF2823")
class ViewController: UIViewController {
@IBOutlet weak var writeLabel: UILabel!
@IBOutlet weak var readLabel: UILabel!
@IBOutlet weak var notifyLabel: UILabel!
var peripjeralManager: CBPeripheralManager!
var write: CBMutableCharacteristic!
var notify: CBMutableCharacteristic!
var timer: Timer?
override func viewDidLoad() {
super.viewDidLoad()
peripjeralManager = CBPeripheralManager(delegate: self, queue: nil)
}
}
extension ViewController: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
switch peripheral.state {
case .unknown:
print("未知")
case .resetting:
print("蓝牙重置中")
case .unsupported:
print("本机不支持BLE")
case .unauthorized:
print("未授权")
case .poweredOff:
print("蓝牙未开始")
case .poweredOn:
print("蓝牙开启")
//primary 创建的服务是否是主服务
let service = CBMutableService(type: serviceUUID, primary: true)
//创建特征
//value 不写死 以便可以修改
write = CBMutableCharacteristic(type: writeUUID, properties: .write, value: nil, permissions: .writeable)
let read = CBMutableCharacteristic(type: readUUID, properties: .read, value: nil, permissions: .readable)
notify = CBMutableCharacteristic(type: notifyUUID, properties: .notify, value: nil, permissions: .readable)
//把特征加入服务
service.characteristics = [write,read,notify]
//把服务加入外设
peripjeralManager.add(service)
//开始广播
peripjeralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [serviceUUID]])
@unknown default:
print("来自未来的错误")
}
}
//添加服务
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
if let error = error {
print("无法添加服务的的原因 \(error.localizedDescription)")
}
}
//开始广播后
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
if let error = error {
print("无法开始广播的的原因 \(error.localizedDescription)")
}
}
//当中心设备发送(对一个或多个特征值的)写入请求时
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
let request = requests[0]
if request.characteristic.properties.contains(.write){
//给当前请求的特征值改值
write.value = request.value
//显示到视图
writeLabel.text = String(data: request.value!, encoding: .utf8)
//给中心设备反馈 以便中心设备可以触发一些delegate方法
peripheral.respond(to: request, withResult: .success)
}else{
peripheral.respond(to: request, withResult: .writeNotPermitted)
}
}
//当中心设备发送数据(某个特征的值)请求时
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
if request.characteristic.properties.contains(.read){
//给request下的value赋值当前请求特征的值 然后随着respond带到中心设备去
//request.value = request.characteristic.value
//这里用文本框中的数据模拟某个特征的值
request.value = readLabel.text!.data(using: .utf8)
writeLabel.text = String(data: request.value!, encoding: .utf8)
peripheral.respond(to: request, withResult: .success)
}else{
peripheral.respond(to: request, withResult: .readNotPermitted)
}
}
//当中心设备订阅了某个特征值时
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
updateNotifyValue()
}
//传输队列有了剩余空间时
func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
updateNotifyValue()
}
//当中心设备取消订阅某个特征值时
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
timer?.invalidate()
}
func updateNotifyValue() {
//用计时器模拟外设数据的实时变动
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy年MM月dd日 HH时mm分ss秒"
let dateStr = dateFormatter.string(from: Date())
self.notifyLabel.text = dateStr
//更新特征值 给一个或多个(第三个参数指定为nil)订阅这个特征的中心设备发送实时数据
//返回bool true -> 发送成功 false -> 传输队列已满
//如果待会有了空间 则调用peripheralManagerIsReady 可在里面再次发送数据
self.peripjeralManager.updateValue(dateStr.data(using: .utf8)!, for: self.notify, onSubscribedCentrals: nil)
}
}
}
网友评论