如何使用 BLE OBDII 外设

Posted

技术标签:

【中文标题】如何使用 BLE OBDII 外设【英文标题】:How to use BLE OBDII Peripheral 【发布时间】:2017-03-03 03:24:14 【问题描述】:

我正在尝试创建一个从 OBDII 蓝牙 4 (LE) 设备读取数据的 ios 应用。我购买了 Vgate icar3 蓝牙(4.0)elm327 OBDII。我把它插到我的车里,找到了宣传某些服务的 IOS-VLink 外围设备。然后我可以获得这些服务的特征。这些是我找到的服务:

<CBService: 0x1780729c0, isPrimary = YES, UUID = Battery>
<CBService: 0x178072a80, isPrimary = YES, UUID = 1803>
<CBService: 0x178072ac0, isPrimary = YES, UUID = 1802>
<CBService: 0x178072b00, isPrimary = YES, UUID = 1811>
<CBService: 0x178072b40, isPrimary = YES, UUID = 1804>
<CBService: 0x178072b80, isPrimary = YES, UUID = 18F0>
<CBService: 0x178072bc0, isPrimary = YES, UUID = Device Information>
<CBService: 0x178072c00, isPrimary = YES, UUID = E7810A71-73AE-499D-8C15-FAA9AEF0C3F2>

但我不知道 1803、1802、1811、1804 和 18F0 服务是什么或如何使用它们。这是我的简单程序,用于找出正在宣传的内容。

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate 

var centralManager = CBCentralManager()
var peripherals = [CBPeripheral]()
@IBOutlet weak var outputTextView: UITextView!

override func viewDidLoad() 
    super.viewDidLoad()
    centralManager.delegate = self


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()


func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) 
    print("connected to \(peripheral.name ?? "unnamed")")
    peripheral.delegate = self
    peripheral.discoverServices(nil)


func centralManagerDidUpdateState(_ central: CBCentralManager) 
    if central.state == .poweredOn 
        central.scanForPeripherals(withServices: nil, options: nil)
    


func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) 
    if peripheral.name == "IOS-Vlink" 
        peripherals.append(peripheral)
        print(peripheral.name ?? "peripheral has no name")
        print(peripheral.description)
        central.connect(peripheral, options: nil)
        central.stopScan()
    



func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) 
    guard let services = peripheral.services else 
        return
    
    for service in services 
        print(service.description)
        peripheral.discoverCharacteristics(nil, for: service)
    


func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) 
    guard let chars = service.characteristics else 
        return
    
    for char in chars 
        print(char.description)
    


【问题讨论】:

我发现这个关于 E7810A... uuid globals.market/offer/… 和这个 bluetooth.com/specifications/gatt/services 关于其他 uuid。还是不知道怎么用。 我有一个类似的问题,这里是答案:***.com/questions/61090365/… 【参考方案1】:

我想通了。 “E7810A71-73AE-499D-8C15-FAA9AEF0C3F2”服务的特征是 uuid 为“BEF8D6C9-9C21-4C9E-B632-BD58C1009F9F”。如果您向该特征写入 AT 命令,则它会调用peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?),然后在 value 属性中获取结果。这是发送简单 ATZ 命令的代码。此时它只是使用正确的 OBDII ELM327 命令。

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate 

var centralManager = CBCentralManager()
var peripherals = [CBPeripheral]()
@IBOutlet weak var outputTextView: UITextView!

override func viewDidLoad() 
    super.viewDidLoad()
    centralManager.delegate = self


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()


func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) 
    print("connected to \(peripheral.name ?? "unnamed")")
    peripheral.delegate = self
    peripheral.discoverServices([CBUUID(string:"E7810A71-73AE-499D-8C15-FAA9AEF0C3F2")])


func centralManagerDidUpdateState(_ central: CBCentralManager) 
    if central.state == .poweredOn 
        central.scanForPeripherals(withServices: nil, options: nil)
    


func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) 
    if peripheral.name == "IOS-Vlink" 
        peripherals.append(peripheral)
        print(peripheral.name ?? "peripheral has no name")
        print(peripheral.description)
        central.connect(peripheral, options: nil)
        central.stopScan()
    



func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) 
    guard let services = peripheral.services else 
        return
    
    for service in services 
        peripheral.discoverCharacteristics([CBUUID(string:"BEF8D6C9-9C21-4C9E-B632-BD58C1009F9F")], for: service)
    


func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) 
    guard let chars = service.characteristics else 
        return
    
    guard chars.count > 0 else 
        return
    
    let char = chars[0]
    peripheral.setNotifyValue(true, for: char)
    peripheral.discoverDescriptors(for: char)

    print (char.properties)
    peripheral.writeValue("ATZ\r\n".data(using: .utf8)!, for: char, type: CBCharacteristicWriteType.withResponse)

    peripheral.readValue(for: char)
    if let value = char.value 
        print(String(data:value, encoding:.utf8) ?? "bad utf8 data")
    


func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) 
    if let value = characteristic.value 
        print(String(data:value, encoding:.utf8)!)
    

func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) 
    print(characteristic.descriptors ?? "bad didDiscoverDescriptorsFor")

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) 
    if let error = error 
        print(error)
    
    print("wrote to \(characteristic)")
    if let value = characteristic.value 
        print(String(data:value, encoding:.utf8)!)
    


【讨论】:

【参考方案2】:

如果您在https://www.bluetooth.com/specifications/gatt/services 上找到指定的服务,您可以点击服务链接获取有关特征的信息。从服务描述中,可以通过特征链接了解更多信息。

例如:0x1804 服务用于传输功率级别。它是一个只读服务,提供 org.bluetooth.characteristic.tx_power_level 特性,如果链接到该特性,可以看到它提供 -100 到 20 之间的有符号 8 位 db 级别。

另一个例子:服务 0x1811 用于警报通知服务。它提供了 5 个独立的特征,org.bluetooth.characteristic.supported_new_alert_category、org.bluetooth.characteristic.new_alert、org.bluetooth.characteristic.supported_unread_alert_category、org.bluetooth.characteristic.unread_alert_status 和 org.bluetooth.characteristic.alert_notification_control_point。服务描述为每个特性提供了简短的解释,并链接到该特性的值的更多详细信息。如果您的设备无法通过语音、SMS、IM 或电子邮件发送消息,这些特征可能没有意义,并且可能不受支持。

【讨论】:

以上是关于如何使用 BLE OBDII 外设的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Swift 中的 BLE 外设特征写入回调中提取数据?

适用于Android的蓝牙低功耗(BLE)外设应用程序

BLE 外设无广告

未调用 BLE 外设委托

BLE在不同设备上的不同外设名称

Android BLE GATT 外设模式通知