简体   繁体   English

如何使用BLE OBDII外设

[英]How to use BLE OBDII Peripheral

I'm trying to create an iOS app that will read from an OBDII Bluetooth 4 (LE) device. 我正在尝试创建一个可以从OBDII蓝牙4(LE)设备读取的iOS应用程序。 I purchased a Vgate icar3 bluetooth(4.0) elm327 OBDII. 我购买了Vgate icar3蓝牙(4.0)elm327 OBDII。 I plug it into my car and find IOS-VLink peripheral that advertises some services. 我将它插入我的汽车并找到宣传某些服务的IOS-VLink外围设备。 I can then get the characteristics for those services. 然后我可以获得这些服务的特征。 These are the services I find: 这些是我找到的服务:

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

But I have no idea what the 1803, 1802, 1811, 1804 and 18F0 services are or how to use them. 但我不知道1803,1802,1811,1804和18F0服务是什么或如何使用它们。 Here is my simple program to find out what is being advertised. 这是我的简单程序,可以找出所宣传的内容。

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

I figured it out. 我想到了。 The "E7810A71-73AE-499D-8C15-FAA9AEF0C3F2" service has a characteristic with a uuid of "BEF8D6C9-9C21-4C9E-B632-BD58C1009F9F". “E7810A71-73AE-499D-8C15-FAA9AEF0C3F2”服务具有“BEF8D6C9-9C21-4C9E-B632-BD58C1009F9F”的特征。 If you write an AT command to that characteristic then it calls peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) and then get the results in the value property. 如果你写一个AT命令到那个特性,那么它调用peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)然后在value属性中得到结果。 Here is the code sending a simple ATZ command. 这是发送简单ATZ命令的代码。 At this point it is simply using the correct OBDII ELM327 commands. 此时它只是使用正确的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)!)
    }
}
}

If you find the assigned service on https://www.bluetooth.com/specifications/gatt/services they you can follow the service link to get information on the characteristic(s). 如果您在https://www.bluetooth.com/specifications/gatt/services上找到已分配的服务,则可以按照服务链接获取有关特征的信息。 From the service description, the characteristic link can be followed for more info. 从服务描述中,可以遵循特征链接以获取更多信息。

For example: The 0x1804 service is for transmit power level. 例如:0x1804服务用于发射功率电平。 It is a read-only service providing a org.bluetooth.characteristic.tx_power_level characteristic which, if linked to, can be seen to provide a signed 8 bit db level between -100 and 20. 它是一个提供org.bluetooth.characteristic.tx_power_level特性的只读服务,如果链接到该特性,可以看到它提供-100到20之间的带符号8位db级别。

Another example: Service 0x1811 is for the alert notification service. 另一个例子:服务0x1811用于警报通知服务。 It provides 5 separate characteristics, 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, and org.bluetooth.characteristic.alert_notification_control_point. 它提供了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。 The service description gives a short explanation for each characteristics and links to further details on the values for that characteristic. 服务描述为每个特征提供简短说明,并链接到该特征值的更多细节。 These characteristics probably don't make sense, and are likely not supported, if your device is not capable of messaging via voice, SMS, IM or email. 如果您的设备无法通过语音,短信,即时消息或电子邮件进行消息传递,则这些特性可能没有意义,并且可能不受支持。

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

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