如何在 ios swift 中将值写入 BLE 设备的特性
How to write a value to characteristc for BLE Device in ios swift
我正在开发 iOS BLE 应用来为手机充电 phone。我做了所有正确的事情来发现特征。首先扫描外围设备并连接到它。发现具有通知和无响应属性的写入的服务(FFB0)和特征(FFB1,FFB2)。
我找到了客户端特征配置描述符。我想向 PCB 发送命令以解锁充电 我想将值写入 FFB2 特性,但外设没有响应。这是我的代码。
我已经搜索了与此相关的所有内容,但我没有找到任何解决方案如果有人解决了这个问题,那将对我有所帮助。
这是客户提供的文件:
每块PCB上都有一个BLE4.0蓝牙模块,每个蓝牙模块都有一个单独的12字节长的地址码,PCB数据通道,Service UUID为OxFFBO,包含两个特征值,分别为OxFFBI和OxFFB2 ,通讯数据长度为1--20字节。
OxFFB1为APP数据下载通道。OxFBB2为蓝牙上传数据通道。
上电进入idle mode,当idle mode时,两个灯会flash.it会发送一个ID码(一个字节)给phone,[=40=中的APP =] 将得到 ID 码(一个字节)。
ID码可以通过phone设置来设置。即通过ID码发送对应的解锁指令
解锁指令为0x55,0xe1,(ID0+1),time,以下为解锁指令说明:
ID0为ID码,"time"为用户解锁时间(5-120分钟),
请注意是二进制转十六进制,
time==05表示5分钟,
time==6表示6分钟,
time ==A 表示 10 分钟,依此类推。
如果PCB的ID0为0xff,
解锁 pcb 60min is:0x55,0xe1,0x00,0x3c;
如果PCB的ID0为0x05,
解锁 PCB 10 分钟是 :0x55 , 0xe1 ,0x06 , 0x0a
当PCB上的MCU收到解锁指令后,开始open输出和计时。
当计时时间结束时,系统再次进入空闲模式。
待机状态下,长按按键进入关机休眠模式
串口波特率设置为9600。
APP发送给MCU的查询指令为0x55 0x01
MCU回复APP的信息格式:0x55,0x02,bat_level,xH,XL(xH XL代表电池当前电压值,
xH——代表高8位,XL---代表低8位)
import CoreBluetooth
let batteryServiceCBUUID = CBUUID(string: "FFB0")
let batteryServiceRequestCBUUID = CBUUID(string: "FFB1")
let batteryServiceRequestCBUUID2 = CBUUID(string: "FFB2")
class ChargingViewController: UIViewController , CBPeripheralDelegate
,CBCentralManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is .unknown")
case .resetting:
print("central.state is .resetting")
case .unsupported:
print("central.state is .unsupported")
case .unauthorised:
print("central.state is .unauthorised")
case .poweredOff:
print("central.state is .poweredOff")
case .poweredOn:
centralManager.scanForPeripherals(withServices: [batteryServiceCBUUID])
print("central.state is .poweredOn")
@unknown default:
fatalError()
}
print("state: \(central.state)")
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(peripheral)
batteryServicePeripheral = peripheral
batteryServicePeripheral.delegate = self
centralManager.stopScan()
centralManager.connect(batteryServicePeripheral)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected=======>\(String(describing: batteryServicePeripheral))")
batteryServicePeripheral.delegate = self
batteryServicePeripheral.discoverServices([batteryServiceCBUUID])
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral,
error: Error?) {
print("Fail To Connect=======>\(String(describing: error))")
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral:
CBPeripheral, error: Error?) {
if error == nil {
print("Disconnected========>\(peripheral)")
}else {
print("Disconnected========>\(String(describing: error))")
}
}
// MARK: - CBPeripheral Delegate Methods
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print("SPAKA:PERIPHERALSERVICES============>\(service)")
peripheral.discoverCharacteristics(nil, for: service)
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let characteristics = service.characteristics {
//else { return }
for characteristic in characteristics {
print(characteristic)
if characteristic.uuid == batteryServiceCBUUID {
peripheral.setNotifyValue(true, for: characteristic)
}
if characteristic.uuid == batteryServiceRequestCBUUID2 {
batteryCharacteristics = characteristic
let str1 = "55e100"
let data = String(format: "%@%@",str1,hexTimeForChar)
guard let valueString = data.data(using: String.Encoding.utf8) else
{return}
peripheral.writeValue(valueString, for: characteristic , type:
CBCharacteristicWriteType.withoutResponse)
print("Value String===>\(valueString.debugDescription)")
peripheral.setNotifyValue(true, for: characteristic)
}
}
}
peripheral.discoverDescriptors(for: batteryCharacteristics)
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
if error == nil {
print("Message sent=======>\(String(describing: characteristic.value))")
}else{
print("Message Not sent=======>\(String(describing: error))")
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic:
CBCharacteristic, error: Error?) {
if error == nil {
print("SPAKA : IS NOTIFYING UPDATED STATE ======>\(characteristic.isNotifying)")
print("SPAKA : UPDATED DESCRIPTION ======>\(String(describing:
characteristic.description))")
}else{
print("SPAKA : ERRORUPDATEDNOTIFICATION\(String(describing: error))")
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("SPAKA: UPDATED VALUE RECEIVED========>\(String(describing: characteristic.value))")
print("characteristic UUID: \(characteristic.uuid), value: \(characteristic.value)")
guard let str = characteristic.value else { return }
if let string = String(bytes: str, encoding: .utf8) {
print("SPAKA==========>:::\(string)")
} else {
print("not a valid UTF-8 sequence")
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
guard let desc = batteryCharacteristics.descriptors else { return }
for des in desc {
print("BEGIN:SPAKA DESCRIPTOR========>\(des)")
discoveredDescriptor = des
print("Descriptor Present Value and uuid: \(des.uuid), value: \(String(describing: des.value))")
peripheral.readValue(for: discoveredDescriptor)
}
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
if let error = error {
print("Failed… error: \(error)")
return
}
print("Descriptor Write Value uuid: \(descriptor.uuid), value: \(String(describing: descriptor.value))")
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
if let error = error {
print("Failed… error: \(error)")
return
}
print("Descriptor Updated Value uuid: \(descriptor.uuid), value: \(String(describing: descriptor.value))")
}
}
关于PDB的信息有点难以破译,但包含了很好的信息。听起来好像 PCB 包含蓝牙到 UART 模块。一种特性是向PCB发送数据,一种特性是从PCB接收数据。
需要发给PCB的命令我还是不明白。如果您可以访问 Android 代码,那么您可以在那里找到答案。
以下是可能的最小代码:
let batteryServiceUUID = CBUUID(string: "FFB0")
let rxCharacteristicUUID = CBUUID(string: "FFB1")
let txCharacteristicUUID = CBUUID(string: "FFB2")
var centralManager: CBCentralManager!
var batteryPeripheral: CBPeripheral? = nil
var batteryService: CBService? = nil
var txCharacteristic: CBCharacteristic? = nil
var rxCharacteristic: CBCharacteristic? = nil
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
centralManager.scanForPeripherals(withServices: [batteryServiceUUID])
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
batteryPeripheral = peripheral
batteryPeripheral!.delegate = self
centralManager.stopScan()
centralManager.connect(batteryPeripheral!)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
batteryPeripheral!.discoverServices([batteryServiceUUID])
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
peripheral.discoverCharacteristics(nil, for: peripheral.services![0])
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
if characteristic.uuid == rxCharacteristicUUID {
rxCharacteristic = characteristic
peripheral.setNotifyValue(true, for: rxCharacteristic!)
} else if (characteristic.uuid == txCharacteristicUUID) {
txCharacteristic = characteristic
}
}
sendInitialCommand()
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let value = characteristic.value {
print("Data received")
print(value as NSData)
}
}
func sendInitialCommand() {
let cmdBytes: [UInt8] = [0x55, 0xe1, 0x00, 0x0a]
let cmd = Data(cmdBytes)
batteryPeripheral!.writeValue(cmd, for: txCharacteristic!, type: .withoutResponse)
}
我正在开发 iOS BLE 应用来为手机充电 phone。我做了所有正确的事情来发现特征。首先扫描外围设备并连接到它。发现具有通知和无响应属性的写入的服务(FFB0)和特征(FFB1,FFB2)。
我找到了客户端特征配置描述符。我想向 PCB 发送命令以解锁充电 我想将值写入 FFB2 特性,但外设没有响应。这是我的代码。
我已经搜索了与此相关的所有内容,但我没有找到任何解决方案如果有人解决了这个问题,那将对我有所帮助。
这是客户提供的文件:
每块PCB上都有一个BLE4.0蓝牙模块,每个蓝牙模块都有一个单独的12字节长的地址码,PCB数据通道,Service UUID为OxFFBO,包含两个特征值,分别为OxFFBI和OxFFB2 ,通讯数据长度为1--20字节。 OxFFB1为APP数据下载通道。OxFBB2为蓝牙上传数据通道。
上电进入idle mode,当idle mode时,两个灯会flash.it会发送一个ID码(一个字节)给phone,[=40=中的APP =] 将得到 ID 码(一个字节)。 ID码可以通过phone设置来设置。即通过ID码发送对应的解锁指令
解锁指令为0x55,0xe1,(ID0+1),time,以下为解锁指令说明:
ID0为ID码,"time"为用户解锁时间(5-120分钟), 请注意是二进制转十六进制, time==05表示5分钟, time==6表示6分钟, time ==A 表示 10 分钟,依此类推。 如果PCB的ID0为0xff, 解锁 pcb 60min is:0x55,0xe1,0x00,0x3c; 如果PCB的ID0为0x05, 解锁 PCB 10 分钟是 :0x55 , 0xe1 ,0x06 , 0x0a
当PCB上的MCU收到解锁指令后,开始open输出和计时。 当计时时间结束时,系统再次进入空闲模式。 待机状态下,长按按键进入关机休眠模式
串口波特率设置为9600。 APP发送给MCU的查询指令为0x55 0x01 MCU回复APP的信息格式:0x55,0x02,bat_level,xH,XL(xH XL代表电池当前电压值, xH——代表高8位,XL---代表低8位)
import CoreBluetooth
let batteryServiceCBUUID = CBUUID(string: "FFB0")
let batteryServiceRequestCBUUID = CBUUID(string: "FFB1")
let batteryServiceRequestCBUUID2 = CBUUID(string: "FFB2")
class ChargingViewController: UIViewController , CBPeripheralDelegate
,CBCentralManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is .unknown")
case .resetting:
print("central.state is .resetting")
case .unsupported:
print("central.state is .unsupported")
case .unauthorised:
print("central.state is .unauthorised")
case .poweredOff:
print("central.state is .poweredOff")
case .poweredOn:
centralManager.scanForPeripherals(withServices: [batteryServiceCBUUID])
print("central.state is .poweredOn")
@unknown default:
fatalError()
}
print("state: \(central.state)")
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(peripheral)
batteryServicePeripheral = peripheral
batteryServicePeripheral.delegate = self
centralManager.stopScan()
centralManager.connect(batteryServicePeripheral)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected=======>\(String(describing: batteryServicePeripheral))")
batteryServicePeripheral.delegate = self
batteryServicePeripheral.discoverServices([batteryServiceCBUUID])
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral,
error: Error?) {
print("Fail To Connect=======>\(String(describing: error))")
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral:
CBPeripheral, error: Error?) {
if error == nil {
print("Disconnected========>\(peripheral)")
}else {
print("Disconnected========>\(String(describing: error))")
}
}
// MARK: - CBPeripheral Delegate Methods
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print("SPAKA:PERIPHERALSERVICES============>\(service)")
peripheral.discoverCharacteristics(nil, for: service)
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let characteristics = service.characteristics {
//else { return }
for characteristic in characteristics {
print(characteristic)
if characteristic.uuid == batteryServiceCBUUID {
peripheral.setNotifyValue(true, for: characteristic)
}
if characteristic.uuid == batteryServiceRequestCBUUID2 {
batteryCharacteristics = characteristic
let str1 = "55e100"
let data = String(format: "%@%@",str1,hexTimeForChar)
guard let valueString = data.data(using: String.Encoding.utf8) else
{return}
peripheral.writeValue(valueString, for: characteristic , type:
CBCharacteristicWriteType.withoutResponse)
print("Value String===>\(valueString.debugDescription)")
peripheral.setNotifyValue(true, for: characteristic)
}
}
}
peripheral.discoverDescriptors(for: batteryCharacteristics)
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
if error == nil {
print("Message sent=======>\(String(describing: characteristic.value))")
}else{
print("Message Not sent=======>\(String(describing: error))")
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic:
CBCharacteristic, error: Error?) {
if error == nil {
print("SPAKA : IS NOTIFYING UPDATED STATE ======>\(characteristic.isNotifying)")
print("SPAKA : UPDATED DESCRIPTION ======>\(String(describing:
characteristic.description))")
}else{
print("SPAKA : ERRORUPDATEDNOTIFICATION\(String(describing: error))")
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("SPAKA: UPDATED VALUE RECEIVED========>\(String(describing: characteristic.value))")
print("characteristic UUID: \(characteristic.uuid), value: \(characteristic.value)")
guard let str = characteristic.value else { return }
if let string = String(bytes: str, encoding: .utf8) {
print("SPAKA==========>:::\(string)")
} else {
print("not a valid UTF-8 sequence")
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
guard let desc = batteryCharacteristics.descriptors else { return }
for des in desc {
print("BEGIN:SPAKA DESCRIPTOR========>\(des)")
discoveredDescriptor = des
print("Descriptor Present Value and uuid: \(des.uuid), value: \(String(describing: des.value))")
peripheral.readValue(for: discoveredDescriptor)
}
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
if let error = error {
print("Failed… error: \(error)")
return
}
print("Descriptor Write Value uuid: \(descriptor.uuid), value: \(String(describing: descriptor.value))")
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
if let error = error {
print("Failed… error: \(error)")
return
}
print("Descriptor Updated Value uuid: \(descriptor.uuid), value: \(String(describing: descriptor.value))")
}
}
关于PDB的信息有点难以破译,但包含了很好的信息。听起来好像 PCB 包含蓝牙到 UART 模块。一种特性是向PCB发送数据,一种特性是从PCB接收数据。
需要发给PCB的命令我还是不明白。如果您可以访问 Android 代码,那么您可以在那里找到答案。
以下是可能的最小代码:
let batteryServiceUUID = CBUUID(string: "FFB0")
let rxCharacteristicUUID = CBUUID(string: "FFB1")
let txCharacteristicUUID = CBUUID(string: "FFB2")
var centralManager: CBCentralManager!
var batteryPeripheral: CBPeripheral? = nil
var batteryService: CBService? = nil
var txCharacteristic: CBCharacteristic? = nil
var rxCharacteristic: CBCharacteristic? = nil
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
centralManager.scanForPeripherals(withServices: [batteryServiceUUID])
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
batteryPeripheral = peripheral
batteryPeripheral!.delegate = self
centralManager.stopScan()
centralManager.connect(batteryPeripheral!)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
batteryPeripheral!.discoverServices([batteryServiceUUID])
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
peripheral.discoverCharacteristics(nil, for: peripheral.services![0])
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
if characteristic.uuid == rxCharacteristicUUID {
rxCharacteristic = characteristic
peripheral.setNotifyValue(true, for: rxCharacteristic!)
} else if (characteristic.uuid == txCharacteristicUUID) {
txCharacteristic = characteristic
}
}
sendInitialCommand()
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if let value = characteristic.value {
print("Data received")
print(value as NSData)
}
}
func sendInitialCommand() {
let cmdBytes: [UInt8] = [0x55, 0xe1, 0x00, 0x0a]
let cmd = Data(cmdBytes)
batteryPeripheral!.writeValue(cmd, for: txCharacteristic!, type: .withoutResponse)
}