How to use BLE OBDII Peripheral

两盒软妹~` 提交于 2020-05-12 01:06:57

问题


I'm trying to create an iOS app that will read from an OBDII Bluetooth 4 (LE) device. I purchased a Vgate icar3 bluetooth(4.0) elm327 OBDII. I plug it into my car and find IOS-VLink peripheral that advertises some services. 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. 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)
    }
}
}

回答1:


I figured it out. The "E7810A71-73AE-499D-8C15-FAA9AEF0C3F2" service has a characteristic with a uuid of "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. Here is the code sending a simple ATZ command. At this point it is simply using the correct OBDII ELM327 commands.

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:


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). From the service description, the characteristic link can be followed for more info.

For example: The 0x1804 service is for transmit power level. 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.

Another example: Service 0x1811 is for the alert notification service. 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. 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.



来源:https://stackoverflow.com/questions/42570070/how-to-use-ble-obdii-peripheral

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!