BLE OBDII外设使用方法
How to use BLE OBDII Peripheral
我正在尝试创建一个将从 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)
}
}
}
如果您在 https://www.bluetooth.com/specifications/gatt/services 上找到指定的服务,您可以关注服务 link 以获取有关特征的信息。从服务描述中,可以遵循特征 link 以获取更多信息。
例如:0x1804 服务用于传输功率级别。它是一种只读服务,提供 org.bluetooth.characteristic.tx_power_level 特性,如果 link 这样做,可以看出它提供了一个介于 -100 和 20 之间的带符号的 8 位数据库级别。
另一个例子:服务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。服务描述对每个特征进行了简短的解释,并 links 进一步详细说明了该特征的值。如果您的设备无法通过语音、SMS、IM 或电子邮件发送消息,这些特征可能没有意义,并且可能不受支持。
我明白了。 "E7810A71-73AE-499D-8C15-FAA9AEF0C3F2" 服务具有 uuid 为 "BEF8D6C9-9C21-4C9E-B632-BD58C1009F9F" 的特征。如果您向该特征写入 AT 命令,那么它会调用 peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)
,然后在值 属性 中获取结果。这是发送简单 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)!)
}
}
}
我正在尝试创建一个将从 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)
}
}
}
如果您在 https://www.bluetooth.com/specifications/gatt/services 上找到指定的服务,您可以关注服务 link 以获取有关特征的信息。从服务描述中,可以遵循特征 link 以获取更多信息。
例如:0x1804 服务用于传输功率级别。它是一种只读服务,提供 org.bluetooth.characteristic.tx_power_level 特性,如果 link 这样做,可以看出它提供了一个介于 -100 和 20 之间的带符号的 8 位数据库级别。
另一个例子:服务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。服务描述对每个特征进行了简短的解释,并 links 进一步详细说明了该特征的值。如果您的设备无法通过语音、SMS、IM 或电子邮件发送消息,这些特征可能没有意义,并且可能不受支持。
我明白了。 "E7810A71-73AE-499D-8C15-FAA9AEF0C3F2" 服务具有 uuid 为 "BEF8D6C9-9C21-4C9E-B632-BD58C1009F9F" 的特征。如果您向该特征写入 AT 命令,那么它会调用 peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)
,然后在值 属性 中获取结果。这是发送简单 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)!)
}
}
}