简体   繁体   English

如何在iOS Swift中将值写入BLE设备的characteristc

[英]How to write a value to characteristc for BLE Device in ios swift

I'm working on iOS BLE app to charge a mobile phone. 我正在使用iOS BLE应用为手机充电。 I did everything correct up to discover characteristics. 我做了一切纠正以发现特征。 First Scanning peripheral and connected to it. 首先扫描外围设备并连接到它。 Discover the services(FFB0) and characteristics(FFB1, FFB2) which having notify and write without response properties. 发现具有通知和写入但没有响应属性的服务(FFB0)和特征(FFB1,FFB2)。

I found the Client Characteristic Configuration Descriptor. 我找到了客户端特征配置描述符。 I want to send the command to PCB to unlock for charging I want write value to FFB2 characteristics but peripheral doesn't respond. 我想将命令发送到PCB以解锁以进行充电我想向FFB2特性写入值,但外设没有响应。 Here is my code. 这是我的代码。

I have searched everything related to this but I didn't find any solution If anybody gives solution to this problem it will be helpful to me. 我已经搜索了与此相关的所有内容,但没有找到任何解决方案。如果有人对此问题提供了解决方案,它将对我有所帮助。

This is Document Provided by client: 这是客户提供的文件:

There is a BLE4.0 Bluetooth module on each of the PCB, each Bluetooth module has a solo 12 bytes length address code, The PCB data channel, Service UUID is OxFFBO, including two eigenvalues, it is OxFFBI and OxFFB2, The length of communication data is 1--20 bytes. 每个PCB上都有一个BLE4.0蓝牙模块,每个蓝牙模块都有一个12字节长的地址代码,PCB数据通道,服务UUID是OxFFBO,包括两个特征值,分别是OxFFBI和OxFFB2,通信长度数据为1--20字节。 OxFFB1 is the channel for APP data download.OxFBB2 is the channel for Bluetooth upload the data. OxFFB1是APP数据下载的通道,OxFBB2是Bluetooth上载数据的通道。

Power-up into idle mode, when in idle mode, the two lights will flash.it will send an ID code(a byte)to the phone, the APP in the phone will get the ID code(a byte). 开机进入空闲模式,在空闲模式下,两个指示灯将闪烁,它将向手机发送一个ID码(一个字节),手机中的APP将获取一个ID码(一个字节)。 ID code can be set by phone settings. 可以通过电话设置来设置ID码。 it means sending the corresponding unlock instruction by ID code. 这意味着通过ID码发送相应的解锁指令。

The unlock instruction is 0x55,0xe1,(ID0+1),time,Following is the explain of unlock instruction: 解锁指令为0x55,0xe1,(ID0 + 1),time,以下为解锁指令说明:

ID0 is a ID code,"time" is the user unlock time(5-120 min), please pay attention to it is binary-to-hexadecimal conversion, time==05 means 5 min, time==6 means 6 min, time ==A means 10 min ,and so on. ID0是一个ID码,“时间”是用户解锁时间(5-120分钟),请注意它是二进制到十六进制的转换,时间== 5表示5分钟,时间== 6表示6分钟,时间== A表示10分钟,依此类推。 If the ID0 of the PCB is 0xff, unlock the pcb 60min is:0x55,0xe1,0x00,0x3c; 如果PCB的ID0为0xff,则解锁pcb 60min为:0x55,0xe1,0x00,0x3c; If the ID0 of the PCB is 0x05, unlock the pcb 10 min is :0x55 , 0xe1 ,0x06 , 0x0a 如果PCB的ID0为0x05,则解锁PCB 10分钟为:0x55、0xe1、0x06、0x0a

It will start open output and timing when the MCU on the PCB receives the unlock instruction. 当PCB上的MCU收到解锁指令时,它将开始打开输出并计时。 The system goes into idle mode again when timing time is out. 计时时间到后,系统再次进入空闲模式。 In idle mode, long press the key goes into shut down sleeping time mode. 在空闲模式下,长按此键可进入关机睡眠时间模式。

The baud rate of uart is set at 9,600. uart的波特率设置为9,600。 The inquiry command that APP send to MCU is 0x55 0x01 MCU should reply to the APP's information format: 0x55, 0x02, bat_level, xH, XL (xH XL represents the current voltage value of the battery, xH - represents the high 8 bits, and XL--- represents the low 8 bits) 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))")

}
}

The information about the PDB is somewhat difficult to decipher but contains good information. 有关PDB的信息在某种程度上很难破译,但其中包含良好的信息。 It sounds as if the PCBs contain a Bluetooth-to-UART module. 听起来好像PCB包含Bluetooth-to-UART模块。 One characteristic is for sending data to the PCB, one characteristic is for receiving data from the PCB. 一种特性是用于将数据发送到PCB,一种特性是用于从PCB接收数据。

I still don't understand the commands that need to be sent to the PCB. 我仍然不明白需要发送到PCB的命令。 If you have access to the Android code, then you can find the answers there. 如果您有权访问Android代码,则可以在此处找到答案。

Below is the minimal code that could potentially: 以下是可能的最小代码:

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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM